《csharp高级编程》 学习笔记 第七章 委托和事件

第七章 委托和事件
回调(callback)函数是windows编程的一个重要部分。
回调函数实际上是方法调用的指针,也称为函数指针,是一个非常强大的编程特性。
.NET以委托的形式实现了函数指针的概念。
但特殊在于,与c函数指针不同,.NET委托是类型安全的。

7.1 委托
委托是一种特殊的对象类型,其特殊之处在于:
我们以前定义的所有对象都包含数据,而委托包含的是只是方法的地址。

7.1.1 在csharp中声明委托
使用委托,需两个步骤:
1.定义
delegate void IntMethodInvoker(int x);
理解委托的一个要点是它们的类型安全性非常高。
在定义委托时,必须给出它所代表的方法签名和返回类型等全部细节。

语法上类似方法的定义,但没有方法体。

***因为定义委托是定义一个新类,故可以在定义类的任何地方定义委托。

注意:
委托实现为派生自基类System. Multicast Delegate的类,System. Multicast Delegate又派生自System.Delegate。

2.创建该委托的实例
注意:
类有两个不同术语:
类和对象。
但委托只有一个术语。
在创建委托的实例时,所创建的委托的实例仍成为委托。

7.1.2 在csharp中使用委托
private delegate string GetAString();
static void Main()
{
int x = 40;
GetAString firstStringMethod = new GetAString(x.ToString);
Console.WriteLine("String is {0}" + firstStringMethod());
// With firstStringMethod initialized to x.ToString(),
// the above statement is equivalent to saying
// Console.WriteLine("String is {0}" + x.ToString()); }

在csharp中,委托在语法上总是带有一个参数的构造函数。
这个参数就是委托引用的方法。
*这个方法必须匹配最初定义委托时的返回值,形参。

给委托实例提供括号与调用委托类的Invoke()方法完全相同。
firstStringMethod();
firstStringMethod. Invoke();

csharp 2.0 使用委托推断扩展了委托的语法。
GetAString firstStringMethod = new GetAString(x.ToString);
GetAString firstStringMethod = x.ToString;
以上两行代码等价,显然后者更简洁。

注意:
给定委托的实例可以表示任何类型的任何对象上的实例方法或静态方法
--只要方法的签名匹配。

7.1.5 多播委托(+=和-+操作符)

委托可以包含多个方法。
如果调用多播委托,就可以按顺序连续调用多个方法。
*但只能得到委托调用的最后一个方法的结果。
*使用多播委托时,注意对同一委托调用方法链的顺序并未正式定义。

注意:
多播委托是一个派生于System.MulticastDelegate 的类。
System. MulticastDelegate又派生于基类System.Delegate。



7.1.6 匿名方法
到目前为止,要想使委托工作,方法必须已经存在。
但其实还有另一种方式:
即通过匿名方法。
匿名方法是用作委托参数的一个代码块。

定义语法和之前没有区别。
但在实例化委托时就有区别。
using System;
namespace Wrox.ProCSharp.Delegates
{
class Program
{
delegate string DelegateTest(string val);
static void Main()
{
string mid = ", middle part,";
delegateTest anonDel = delegate(string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("Start of string"));
}
}
}
注意此时在定义anonDel时,不是传送已知的方法名。
而是使用一个简单的代码块。

匿名方法的优点是减少了编写的代码。
但是使用匿名方法时,代码执行得不太快。
编译器仍定义了一个方法,该方法只有一个自动指定的名称。

7.1.7 λ表达式
csharp 3.0 为匿名方法提供新语法:λ表达式。
using System;
namespace Wrox.ProCSharp.Delegates
{
class Program
{
delegate string DelegateTest(string val);
static void Main()
{
string mid = ", middle part,";
DelegateTest anonDel = param = >
{
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("Start of string"));
}
}
}

7.1.8 协变和抗变
委托调用的方法不需要与委托声明定义的类型相同。
因此可能出现协变和抗变。
1.返回类型协变
方法的返回类型可以是派生于委托定义的类型。
我的理解是“兼容”即可。
2.参数类型抗变
委托定义的参数可以不同于委托调用的方法。
这里的“不同”同理1。

7.2 事件(event)
.NET把这些传送来的消息封装在事件中。
如果需要相应某个消息,就处理对应的事件。

有一定windows编程基础的人对这里的事件都不会陌生吧。我的理解即是消息响应。

委托就用作应用程序接受到消息时封装事件的方式。

*microsoft设计csharp事件的目的是让用户无需理解底层的委托,就可以使用它们。

注意:
这里的术语“事件”有两种不同的含义。
第一,表示发生了某件有趣的事。
第二,表示csharp语言中已定义的一个对象,即处理通知过程的对象。

7.2.1 从接收器的角度讨论事件
事件接收器是指在发生某些事情时被通知的应用程序、对象或组件。

*而发送器可以是应用程序中的另一个对象或程序集,在系统事件中,例如鼠标单击,发送器就是.NET运行库。

public Form1()
{
InitializeComponent();
buttonOne.Click += new EventHandler(Button_Click);
}

注意:
1.返回值总是void。事件处理程序不能有返回值。
2.参数:
只要使用EventHandler委托,参数就应是object和EventArgs。

第一个参数是引发事件的对象。
第二个包含有关时间的有用信息的对象。
其实对于有一定MFC基础的人对这些就很熟悉了吧。

在windows用户界面上,microsoft已经编写了所有需要的事件发送器。
他们都在.NET基类中,在windows.form 命名空间中。


*我的理解是其实这个光看书不好懂,关键是自己建几个项目看看框架的代码就一目了然了。

7.2.2 生成事件
书上举了一个例子,此处略。

7.3 小结
.NET开发人员大量使用委托和事件,特别是开发windows forms应用程序。
其实要真正理解委托和事件,就动手去开发个小的windows forms程序是最好的办法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值