【C#与.NET程序设计】(8)- C#事件、Lambda

事件(Event)

  • 其实质就是具有特殊签名的委托,事件处理的就是委托链表的方法
  • 事件可以解决委托带来的“封装不完善”的问题
    由于delegate的目的是为了将其暴露在类的客户端进行方法的注册,因此必须是 public 的
    但这样一来,在客户端就可以对其进行随意的函数绑定,严重破坏对象的封装性
  • 对于事件,无论内部的委托类型是 public 还是 protected,它总是 private的;在类的外部,注册“+=”和注销“-=”的访问限定符与委托类型限定符一致

事件的具体描述

事件是类在发生其关注的事情时用来提供通知的一种方式

牵涉到2个角色:
1. 事件发布者:这个对象维护状态信息,当发生改变时便触发一个事件,并通知所有的事件订阅者
2. 事件订阅者:可以注册感兴趣的事件,在发布者触发一个事件后自动执行这段代码

// 代码来自:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1703763.html

//发布者(Publiser)
public class Publisher
{
    //声明一个出版的委托
    public delegate void PublishEventHander();
    //在委托的机制下我们建立一个出版事件
    public event PublishEventHander OnPublish;
    //事件必须要在方法里去触发,出版社发布新书方法
    public void issue()
    {
        //如果有人注册了这个事件,也就是这个事件不是空
        if (OnPublish != null)
        {
            Console.WriteLine("最新一期的《火影忍者》今天出版哦!");
            OnPublish();
        }
    }
}

//Subscriber 订阅者,无赖小明
public class MrMing
{
    //对事件感兴趣的事情,这里指对出版社的书感兴趣
    public static void Receive()
    {
        Console.WriteLine("嘎嘎,我已经收到最新一期的《火影忍者》啦!!");       
    }
}

//Subscriber 订阅者,悲情人物小张
public class MrZhang
{
    //对事件感兴趣的事情
    public static void Receive()
    {
        Console.WriteLine("幼稚,这么大了,还看《火影忍者》,SB小明!");
    }
}

class Story
{
    public static void Main(string[] args)
    {
        //实例化一个出版社
        Publisher publisher = new Publisher(); 

        //给这个出火影忍者的事件注册感兴趣的订阅者,此例中是小明
        publisher.OnPublish += new Publisher.PublishEventHander(MrMing.Receive);
        //另一种事件注册方式
        //publisher.OnPublish += MrMing.Receive;

        //发布者在这里触发出版火影忍者的事件
        publisher.issue();

        Console.ReadKey();
    }
}

事件的匿名

一般来说上面的 Receive 函数只是为了响应事件的调用,为了更简洁(不用去想方法名字),可以使用匿名的方式

class Story
{
    public static void Main(string[] args)
    {
        Publisher publisher = new Publisher(); 
        publisher.OnPublish += delegate{
            // 实现 Receive 的逻辑 
        };  // 注意有个分号

        publisher.issue();
        Console.ReadKey();
    }
}

Lambda

微软对C#的路线是: 委托 -> 匿名表达式 -> Lambda表达式
搬自文章《C# Lambda表达式》,对照下一个加法在三种方式下的实现

delegate int calculator(int x, int y); //委托类型

// 委托
public static int Adding(int x, int y)
{
    return x + y;
}
static void Main()
{
    calculator cal = new calculator(Adding);
    int He = cal(1, 1);
    Console.Write(He);
}

// 对委托类型的简化
// Action<T>
static void Main()
{
    Action<int, int> cal = new Action<int, int>(Adding);

    int he = cal(1, 1);
    Console.Write(he);
}

// Func<T>
// 相较 Action,最后一个参数为输出参数
static void Main()
{
    Func<int, int, void> cal = new Func<int, int>(Adding);

    int he = cal(1, 1);
    Console.Write(he);
}

// 对委托函数的简化
// 匿名
static void Main()
{
    calculator cal = delegate(int num1,int num2)
    {
        return num1 + num2;
    };
    int he = cal(1, 1);
    Console.Write(he);
}

// Lambda
static void Main()
{
    calculator cal = (x, y) => x + y;
    int he = cal(1, 1);
    Console.Write(he);
}

可以看到Lambda的基本形式:(输入参数)=>表达式

  • 只有1个参数时,可以省略括号:()=>、(x)=>、x=>、(x,y)=>
  • 包含多个表达式时,使用“{}+;”:(x)=>{语句1;语句2;};

一般结合 Func 达到委托类型和委托函数的简化

static void Main(string[] args)
{
    Func<int, int, bool> gwl = (p, j) =>
    {
        if (p + j == 10)
        {
            return true;
        }
        return false;
    };
    Console.WriteLine(gwl(5,5) + "");
    Console.ReadKey();
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值