委托,lambda表达式和事件

要区分三者之间的联系与区别首先要明白它们的定义

什么是委托?

委托是类型安全的类,它定义了返回类型和参数类型。委托由关键字delegate来声明

什么情况使用委托?

当要把方法传送给其他方法是,需要使用委托。

既然委托是将方法作为参数传递它,那么委托与指针有什么联系?

委托是面向对象,是类型安全的。

在C++中,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。

委托包含:普通委托,lambda表达式和匿名方法,事件

一、普通委托(单路委托,多播委托,泛型委托(Action<T>和Func<T>))

定义一个委托类的语法:

	[访问限制符] delegate [返回值类型] [委托类的名称]( [参数列表] ); 
1.单路委托( 单路委托就是和方法建立一对一的关系

2.多播委托(多播委托就是和方法建立一对多的关系

3.泛型委托

泛型Action<T>委托类表示引用一个void返回类型的方法

Func<T>委托的使用方式和Action<T>委托类似.Func<T>允许调用带有返回值的方法

二、匿名方法和lambda表达式

1.匿名方法(是用作委托的参数的一段代码)

用匿名方法定义委托的语法与前面的定义没有区别,但在实例化委托时有所区别,如下实例说明了如何使用匿名方法

static void Main()
{
	string mid=",middle part,";
	Func<string,string> anonDel=delegate(string param)
	{
		param +=mid;
		param +="and this was added to the string.";
		return param;
	};//结尾的";"别忘记
	Console.WriteLine(anonDel("Start of string"));
}

/*使用匿名委托的时,要遵守两个原则

1、匿名方法中不能有跳转语句(break, goto或continue)跳转到匿名方法的外部,反之,外部代码也不能跳转到该匿名方法内部。

2、在匿名方法中不能访问不安全代码。
注意:不能访问在匿名方法外部使用的ref和out参数。*/

2.Lambda表达式(只要有委托参数类型的地方,就可以使用Lambda表达式)

语法:

[委托类] [委托对象名] = ( [参数列表] ) => { /*代码块*/ };	   //结尾还是有一个分号
将前面使用匿名方法的例子改为lambda表达式:
static void Main()
{
	string mid=",middle part,";
	Func<string,string> lambda=param=>
	{
		param +=mid;
		param +="and this was added to the string.";
		return param;
	};//结尾的";"别忘记
	Console.WriteLine(lambda("Start of string"));
}

三、事件

事件基于委托,为委托提供了一种发布/订阅机制。事件是一种特殊多播委托,换句话来说,事件是经过深度封装的委托。一个事件简单的可以看作一个多播委托加上两个方法(+=订阅消息和-=取消订阅)。

1、普通事件

        我们使用event关键字来声明事件,语法如下:

[访问权限修饰符] event [委托类类名] [名称];

事件一般是用于通知代码发生了什么。由此我们又可以引出两个概念:1、事件发布方2、事件侦听方。我们现在用一个简单的例子来说明这两个概念,我们以烧开水为例,当水温为95至100度时发出警报。我们先来定义在事件发生时,需要传输的数据成员:

public class Water	//事件发布程序中的基本数据成员类
{
    public int Temperature { get; private set; }
    public Water(int t)
    {
        this.Temperature = t;
    }
}

有了传输的数据,那么我们现在就可以定义事件触发类::

public delegate void WaterHandler(object sender, Water w);     //sender为事件发送者,w为发送的数据
public class Heater	//事件发布程序中的,事件触发类
{
    public event WaterHandler WaterEvent;    //深度的封装委托
    public void HeatWater()	//该方法用于触发事件
    {
        for (int i = 0; i < 101; i++)
        {
            if (i > 95 && i < 101)
            {
                RegWaterEvent(i);		//触发事件
            }
        }
    }
    protected virtual void RegWaterEvent(int t)
    {
        WaterHandler temp = WaterEvent;
        if (temp != null)	
            temp(this, new Water(t));	//如果委托不为空,我们就执行委托,我们无需知道具体执行了哪些方法
    }
}

       现在我们已经完整了定义好了事件发布方了,通过这个例子我们也知道了事件发布方由两部分组成:1、基本数据类   2、事件触发类。接下来我们继续看看事件侦听方又是怎么样的:

public class Alarm	//事件侦听类
{
    public void Waring(object sender, Water w)		//侦听接口,由于侦听事件的发布
    {
        Console.WriteLine("当前水温已经到达 {0} ℃!", w.Temperature);
    }
}

      通过这个例子我们可以发现,事件侦听类,只需有一个和被监听事件一致的方法即可。

Heater heater = new Heater();		//生成事件发布实例
Alarm alarm = new Alarm();
heater.WaterEvent += alarm.Waring;	//对事件发布方进行订阅(侦听),反之我们使用-=取消订阅
heater.HeatWater();			//触发事件,那么现在Alarm类对象alarm将会侦听到这次事件

        通过上述例子我们就大致的了解了事件的工作情况,以及事件发布方和事件侦听方的概念。

       .Net平台为我们提供了泛型委托EventHandler<T>,有了这个泛型委托之后我们就不在需要定义委托类了。我们来看看泛型委托EventHandler<T>的原型:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e)
where TEventArgs: EventArgs;
       参数列表中第一个参数是对象,包含事件的发送者,第二个参数提供了事件的相关信息。现在我们定义事件时,只需让基本数据类继承EventArgs,然后我们就能泛型委托来定义事件了。
注意 :事件只能在本类型内部“触发”,委托不管在本类型内部还是外部都可以“调用”。事件在类的外部只能使用+=或-=来增加/取消订阅


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值