C#笔记 委托与事件
2013-12-19 13:41
363 查看
本文内容:
[b] 1. 委托定义[/b]
[b][b] 2. 申明委托[/b][/b]
[b][b][b] 3. 委托的实例化[/b][/b][/b]
[b][b][b][b] 4. 委托的调用[/b][/b][/b][/b]
[b][b][b][b][b] 5. 匿名方法[/b][/b][/b][/b][/b]
[b][b][b][b][b][b] 6.
委托程序实例 [/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b] 7. 事件定义[/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b] 8. 事件的申明[/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b] 9. 事件的调用[/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b] 10. 事件订阅与移除[/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][b] 11. [b]事件程序实例 [/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][b][b] 12. 标准化事件的设计[/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
1. 委托定义
委托(Delegate)是C#或者.NET中表示强类型方法的特殊类型。比较接近于C语言中的函数指针。(指向函数入口地址的数据类型)。读到这里说下C语言的两个概念:指针函数和函数指针。
指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针。
函数指针是指向函数的指针变量,即本质是一个指针变量。
因此由上面可以看出,委托其实是一种封装好的函数指针。
2. 申明委托
申明委托使用delegate关键字,语法是:
[<修饰符>] delegate <返回类型> <委托名> ([<形参表>])
修饰符:new、public、protected、internal、private。如果在namespace下,只能用public,internal 。
返回类型:与方法的返回类型相同
委托名:与其他类型的标识符要求相同,常用handler作后缀
形参表:与方法的形参表的要求相同
举例:delegate void D1(int i, double d);
3.委托的实例化
由于委托类似方法指针,申明委托时给出的返回类型和形参表,实际上是指该委托所能指向或者封装的方法的返回类型和参数表。
凡是与委托的返回类型和形参表相同的方法,不管是静态的还是实例的,称为与委托的类型兼容,都可以被该委托的实例封装。
委托类型定义后,可以像其他类型一样申明该类型的变量,并对变量实例化。
对委托进行实例化的写法为:
new <委托类型名> (<表达式>)
这里,表达式可以是一个兼容的静态方法、实例方法、或者一个委托实例。
例如:
从某个方法创建一个委托实例时,该委托实例将封装此方法,此时,它的调用列表只包含一个进入点。 可用 +和 += 运算符组合委托实例,用 -和 -= 运算符将一个委托从委托组合中移除。
当组合两个或多个非空委托实例时,它们的调用列表被连接在一起(按照左操作数在先、右操作数在后的顺序)以组成一个新的调用列表,它包含了两个或更多个“进入点”。
例如:委托的组合及调用列表
4.委托的调用
直接使用委托实例名和一组符合要求的参数可以调用该委托。
调用一个委托实例,就是依次调用其调用列表中的方法。使用的是同一组参数。
委托实例可以多次出现在一个调用列表中。这种情况下,它每出现一次,就会被调用一次。从这样的调用列表中移除委托,实际上移除的是调用列表中最后出现的那个委托实例。
5.匿名方法
匿名方法是指初始化委托时内联申明的方法。
6.委托程序实例
7.事件定义
事件也是类的成员之一,也是一个特殊的委托类型。相当于一个类型为委托的字段或属性;
事件是当发生某些事情时,类向该类的使用者(其他类)提供通知的一种方法。
8.事件的申明
C#中申明事件的格式之一为:
<事件修饰> event <委托类型> <事件名称>;
事件修饰可以为:new,public,protected,internal,private,Static,virtual,Sealed,override,abstract,extern
例如:
public event ChangedEventHandler Changed;
这里,ChangedEventHandler是委托类型。必须事先申明,且必须至少具有与事件本身一样的可视性。 如:
声明事件的方法与声明委托类型的字段类似,只是关键字 event 在事件声明前面,在修饰符后面。事件通常被声明为公共事件,但允许任意可访问修饰符。
9.事件的调用
在定义事件的类里面,可以像使用字段那样使用事件(检查其值和给其赋值);
在发生需要通知客户类的事情时,调用事件。由于事件本质上是委托类型,调用事件与调用委托一样。写法为:
<事件名>([<实参表>]);
例如:If (Changed != null) Changed(this,e);
10.事件订阅与移除
在定义事件的类外部,只能将委托实例添加到事件的调用列表中或从中移出。写法同对委托的操作。例如:
List.Changed += new ChangedEventHandler(ListChanged);
或
List.Changed -= new ChangedEventHandler(ListChanged);
重要换句话说,在类外部不可以调用事件,或像使用变量一样使用事件
这就是事件不同于委托的地方,也是不能完全用委托代替事件的原因。
11.[b]事件程序实例 [/b]
12.标准化事件的设计
事件可以是系统定义的委托类型,也可以是自己定义的任何委托类型;
但最好采用标准的委托类型;
标准的事件委托类型有两个参数。
引发事件的对象(命名为:sender)
包含与事件有关数据的参数对象
注意,第二个参数包含所有事件数据。因此需要自己根据需要定义。定义时必须继承系统定义的EventArgs类。
事件参数类定义举例:
13.在程序中定义和使用事件的过程:
1.定义委托类型;
2.定义事件参数类型;
3.在类中定义事件;
4.编写事件处理方法(必须符合委托要求);
5.用事件处理方法初始化委托实例;
6.将委托实例添加到事件的调用列表;
7.触发事件。
本文内容:
[b] 1. 委托定义[/b]
[b][b] 2. 申明委托[/b][/b]
[b][b][b] 3. 委托的实例化[/b][/b][/b]
[b][b][b][b] 4. 委托的调用[/b][/b][/b][/b]
[b][b][b][b][b] 5. 匿名方法[/b][/b][/b][/b][/b]
[b][b][b][b][b][b] 6.
委托程序实例 [/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b] 7. 事件定义[/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b] 8. 事件的申明[/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b] 9. 事件的调用[/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b] 10. 事件订阅与移除[/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][b] 11. [b]事件程序实例 [/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][b][b] 12. 标准化事件的设计[/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b][b][b][b][b][b][b][b][b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
1. 委托定义
委托(Delegate)是C#或者.NET中表示强类型方法的特殊类型。比较接近于C语言中的函数指针。(指向函数入口地址的数据类型)。读到这里说下C语言的两个概念:指针函数和函数指针。
指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针。
int *fun(x);
函数指针是指向函数的指针变量,即本质是一个指针变量。
int (*f) (int x); /* 声明一个函数指针 */ f=function; /* 将function函数的首地址赋给指针f */
因此由上面可以看出,委托其实是一种封装好的函数指针。
2. 申明委托
申明委托使用delegate关键字,语法是:
[<修饰符>] delegate <返回类型> <委托名> ([<形参表>])
修饰符:new、public、protected、internal、private。如果在namespace下,只能用public,internal 。
返回类型:与方法的返回类型相同
委托名:与其他类型的标识符要求相同,常用handler作后缀
形参表:与方法的形参表的要求相同
举例:delegate void D1(int i, double d);
3.委托的实例化
由于委托类似方法指针,申明委托时给出的返回类型和形参表,实际上是指该委托所能指向或者封装的方法的返回类型和参数表。
凡是与委托的返回类型和形参表相同的方法,不管是静态的还是实例的,称为与委托的类型兼容,都可以被该委托的实例封装。
委托类型定义后,可以像其他类型一样申明该类型的变量,并对变量实例化。
对委托进行实例化的写法为:
new <委托类型名> (<表达式>)
这里,表达式可以是一个兼容的静态方法、实例方法、或者一个委托实例。
例如:
delegate void D(int x); //申明委托 class C { public static void M1(int i) {...} public void M2(int i) {...} } class Test { static void Main() { D cd1 = new D(C.M1); // 用静态方法 C t = new C(); // 实例化有关类 D cd2 = new D(t.M2); // 用实例方法 D cd3 = new D(cd2); // 用一个委托实例 } }
从某个方法创建一个委托实例时,该委托实例将封装此方法,此时,它的调用列表只包含一个进入点。 可用 +和 += 运算符组合委托实例,用 -和 -= 运算符将一个委托从委托组合中移除。
当组合两个或多个非空委托实例时,它们的调用列表被连接在一起(按照左操作数在先、右操作数在后的顺序)以组成一个新的调用列表,它包含了两个或更多个“进入点”。
例如:委托的组合及调用列表
delegate void D(int x); class C { public static void M1(int i) {...} public static void M2(int i) {...} } class Test { static void Main() { D cd1 = new D(C.M1); // M1 D cd2 = new D(C.M2); // M2 D cd3 = cd1 + cd2; // M1 + M2 D cd4 = cd3 + cd1; // M1 + M2 + M1 D cd5 = cd4 – cd1; // M1 + M2 } }
4.委托的调用
直接使用委托实例名和一组符合要求的参数可以调用该委托。
调用一个委托实例,就是依次调用其调用列表中的方法。使用的是同一组参数。
委托实例可以多次出现在一个调用列表中。这种情况下,它每出现一次,就会被调用一次。从这样的调用列表中移除委托,实际上移除的是调用列表中最后出现的那个委托实例。
5.匿名方法
匿名方法是指初始化委托时内联申明的方法。
6.委托程序实例
using System; namespace delegateExam { /// <summary> /// Class1 的摘要说明。 /// </summary> delegate void TestDelegate(); //在名称空间下申明委托 class Class1 { /// <summary> /// 应用程序的主入口点。 /// </summary> TestDelegate TD; //申明委托类型的字段 [STAThread] static void Main(string[] args) { // // TODO: 在此处添加代码以启动应用程序 // TestDelegate TD1 = new TestDelegate(Class1.MethodA); //在方法中申明委托实例并用静态方法初始化 TestDelegate TD2 = new TestDelegate(test.method2); //在方法中申明委托实例并用静态方法初始化 Class1 aClass1 = new Class1(); test aTest = new test(); TD2 += new TestDelegate(aClass1.MethodB); //加上实例方法 TD1 += new TestDelegate(aTest.method1); //加上实例方法 Console.WriteLine("调用委托TD1..."); TD1(); Console.WriteLine("调用委托TD2..."); TD2(); TD1 += TD2; //合并两个委托的调用列表 Console.WriteLine("调用委托TD1和TD2..."); TD1(); TD1 -= TD2; Console.WriteLine("移除TD2..."); //移除委托TD2 TD1(); TD1 += delegate { Console.WriteLine("添加匿名方法..."); };//添加匿名方法 TD1(); Console.WriteLine("赋值给委托类型的字段..."); aClass1.TD = TD2; //给字段赋值 aClass1.TD(); Console.ReadLine(); } static void MethodA() { Console.WriteLine("类Class1的静态方法MethodA."); } public void MethodB() { Console.WriteLine("类Class1实例方法MethodB."); } } class test { public void method1() { Console.WriteLine("类test的实例方法method1."); } public static void method2() { Console.WriteLine("类test的静态方法method2."); } } }
7.事件定义
事件也是类的成员之一,也是一个特殊的委托类型。相当于一个类型为委托的字段或属性;
事件是当发生某些事情时,类向该类的使用者(其他类)提供通知的一种方法。
8.事件的申明
C#中申明事件的格式之一为:
<事件修饰> event <委托类型> <事件名称>;
事件修饰可以为:new,public,protected,internal,private,Static,virtual,Sealed,override,abstract,extern
例如:
public event ChangedEventHandler Changed;
这里,ChangedEventHandler是委托类型。必须事先申明,且必须至少具有与事件本身一样的可视性。 如:
public delegate void ChangedEventHandler(object sender, EventArgs e);
声明事件的方法与声明委托类型的字段类似,只是关键字 event 在事件声明前面,在修饰符后面。事件通常被声明为公共事件,但允许任意可访问修饰符。
9.事件的调用
在定义事件的类里面,可以像使用字段那样使用事件(检查其值和给其赋值);
在发生需要通知客户类的事情时,调用事件。由于事件本质上是委托类型,调用事件与调用委托一样。写法为:
<事件名>([<实参表>]);
例如:If (Changed != null) Changed(this,e);
10.事件订阅与移除
在定义事件的类外部,只能将委托实例添加到事件的调用列表中或从中移出。写法同对委托的操作。例如:
List.Changed += new ChangedEventHandler(ListChanged);
或
List.Changed -= new ChangedEventHandler(ListChanged);
重要换句话说,在类外部不可以调用事件,或像使用变量一样使用事件
这就是事件不同于委托的地方,也是不能完全用委托代替事件的原因。
11.[b]事件程序实例 [/b]
using System; //下面的程序展示了标准委托的定义、事件的定义、事件处理方法的定义及他们的综合应用 //程序将列出0到100之间的所有偶数 namespace eventExam { //定义委托类型 delegate void EvenNumberHandler(object sender, OnEvenNumberEventArgs args); //定义参数类 public class OnEvenNumberEventArgs : EventArgs { private int EvenNumber; //存放偶数的字段 public OnEvenNumberEventArgs(int evenNumber) //构造方法 { this.EvenNumber = evenNumber; } public int Number //返回当前偶数的只读属性 { get { return EvenNumber; } } } //包含有事件的类 class Counter { public event EvenNumberHandler OnEvenNumber; //定义事件 public Counter() { OnEvenNumber = null; //在构造方法中,给事件赋初值。只有在定义事件的类中可以这样。 } //触发事件的方法 public void CountTo100() { int CurrentNumber; for(CurrentNumber=0;CurrentNumber<=100;CurrentNumber++) { if(CurrentNumber % 2 == 0) //如果为偶数 { if (OnEvenNumber != null) //如果事件的调用列表不是空的 { OnEvenNumberEventArgs theArgs = new OnEvenNumberEventArgs(CurrentNumber); OnEvenNumber(this, theArgs); //触发事件(其实就是调用委托) } } } } } //对事件进行处理的类 class EvenNumberHandlerClass { //对事件进行处理的方法 public void EvenNumberFound(object sender, OnEvenNumberEventArgs args) { Console.Write(args.Number); Console.Write("; "); } } /// <summary> /// Class1 的摘要说明。 /// </summary> class MainClass { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { Counter MyCounter = new Counter(); //申明并初始化事件发生的对象 //申明并初始化事件处理对象 EvenNumberHandlerClass MyEvenNumberHandlerClass = new EvenNumberHandlerClass(); //将事件发生对象的事件安装上事件处理方法。写法同对委托变量的处理。 MyCounter.OnEvenNumber += new EvenNumberHandler(MyEvenNumberHandlerClass.EvenNumberFound); MyCounter.CountTo100(); Console.ReadLine(); } } }
12.标准化事件的设计
事件可以是系统定义的委托类型,也可以是自己定义的任何委托类型;
但最好采用标准的委托类型;
标准的事件委托类型有两个参数。
引发事件的对象(命名为:sender)
包含与事件有关数据的参数对象
注意,第二个参数包含所有事件数据。因此需要自己根据需要定义。定义时必须继承系统定义的EventArgs类。
事件参数类定义举例:
public class OnEvenNumberEventArgs : EventArgs { private int EvenNumber; public OnEvenNumberEventArgs(int evenNumber) { this.EvenNumber = evenNumber; } public int Number { get { return EvenNumber; } } }
13.在程序中定义和使用事件的过程:
1.定义委托类型;
2.定义事件参数类型;
3.在类中定义事件;
4.编写事件处理方法(必须符合委托要求);
5.用事件处理方法初始化委托实例;
6.将委托实例添加到事件的调用列表;
7.触发事件。
相关文章推荐
- Tolua使用笔记六:在lua中操作C#的委托事件与在lua中对Unity的GameObject的操作
- 早些学C#时对委托和事件的理解笔记
- C#基础笔记——委托(Delegate)和事件(Event)
- C#学习笔记 委托和事件
- C#中的委托与事件 笔记
- [读书笔记]C#学习笔记二: 委托和事件的用法及不同.
- Modern C# 系列课程笔记 第11节 深入委托和事件
- 学习笔记之---C#中的委托与事件
- C#事件 委托 学习笔记
- Tolua使用笔记六:在lua中操作C#的委托事件与在lua中对Unity的GameObject的操作
- 《C#高级编程》学习笔记------C#中的委托和事件(续)
- [读书笔记]C#学习笔记二: 委托和事件的用法及不同
- C#与.NET4 高级程序设计-----委托、事件 学习笔记
- 【unity3d-C#学习笔记】C#中的委托和事件
- C#学习笔记8——C# 中的委托和事件
- C#笔记 委托 事件 匿名方法 Action
- [读书笔记]C#学习笔记二: 委托和事件的用法及不同.
- C#委托与事件学习笔记
- C#学习笔记--详解委托,事件与回调函数
- [学习笔记]c#中的委托、事件、Func、Predicate、Observer设计模式以及其他