浅析C#中的委托
2015-08-25 10:10
447 查看
委托是寻址方法的.NET版本。在C++中,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。而.NET委托完全不同,委托是安全类型的类,它定义了返回类型和参数的类型。
当把方法传递给其他方法时,需要使用委托。
C#中使用一个类时,分两个阶段。首先需要定义这个类,即告诉编译器这个类由什么组成的。然后,实例化一个对象(除非只使用静态方法)。
对于委托也是类似,也需要两个步骤。首先必须定义要使用的委托,然后必须创建该委托的一个或多个实例。
定义语法:
定义委托基本上是定义一个新类,所以可以在定义类的任何相同地方定义委托。即可以在另一个类的内部定义,可以在任何类的外部定义,可以在名称空间中把委托定义为顶层对象。
根据委托定义的可见性,和委托的作用域,可以在委托的定义上应用任意常见的访问修饰符:public、private、protected等
例如:
使用委托:
由上述代码可以看到,C#的委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法,但是这个方法必须匹配最初定义委托时的签名。
实际上,给委托实例提供圆括号与调用委托类的Invoke()方法完全相同。使用Invoke完成一个委托方法的封送,就类似于使用SendMessage方法来给界面线程发送消息,是一个同步方法。也就是说在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞。
因为firstStringMethod 是一个委托类型的变量,所以C#编译器会用firstStringMethod.Invoke()代替firstStringMethod ()。
为了减少输入量,只需要委托实例,就可以只传递地址的名称,即委托推断。
注意:输入行事不能是x.ToString(),也不能把它传给委托变量。x.ToString表示把方法的地址赋予委托变量。
多播委托:
委托可以包含多个方法,这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。但是,委托的签名必须返回void,否则只能得到委托调用的最后一个方法的结果。
多播委托示例程:
解析:
上面的示例程序分别定义了名为method1 和 method2的两个接受整型参数、返回类型为void的方法。
在Main函数里使用下面的声明创建委托对象:
Delegate_Multicast func = new Delegate_Multicast(Method1);
然后使用+= 来添加委托,使用-=来移除委托。
合并委托:
委托对象的一个用途在于,可以使用 + 运算符将它们分配给一个要成为多路广播委托的委托实例。组合的委托可调用组成它的那两个委托。只有相同类型的委托才可以组合。
- 运算符可用来从组合的委托移除组件委托。
匿名方法:
到目前为止,要想使用委托工作,方法必须已经存在。但是还有另一种使用委托的方法:即通过匿名方法。匿名方法是用作委托的参数的一段代码。
用匿名方法定义委托的语法与前面的定义并没有区别。但在实例化的时候就有了区别了。
如果使用匿名方法,则不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。
例如,如果创建方法所需的系统开销是不必要的,在委托的位置指定代码块就非常有用。启动新线程即是一个很好的示例。无需为委托创建更多方法,线程类即可创建一个线程并且包含该线程执行的代码。
委托类型派生自 .NET Framework 中的 Delegate 类。 委托类型是封装的,它们不能派生出其他类,也不能从 Delegate 派生出自定义类。 由于实例化的委托是一个对象,因此可以作为参数传递或分配给一个属性。 这允许方法作为参数接受委托并在稍后调用委托。 这被称为异步回调,是在长进程完成时通知调用方的常用方法。 当以这种方式使用委托时,使用委托的代码不需要知道要使用的实现方法。 功能类似于封装接口提供的功能。
当把方法传递给其他方法时,需要使用委托。
C#中使用一个类时,分两个阶段。首先需要定义这个类,即告诉编译器这个类由什么组成的。然后,实例化一个对象(除非只使用静态方法)。
对于委托也是类似,也需要两个步骤。首先必须定义要使用的委托,然后必须创建该委托的一个或多个实例。
定义语法:
delegate void IntMethodInoker(int x); delegate double TwoLongsOp(long first, long second); delegate string GetString();
定义委托基本上是定义一个新类,所以可以在定义类的任何相同地方定义委托。即可以在另一个类的内部定义,可以在任何类的外部定义,可以在名称空间中把委托定义为顶层对象。
根据委托定义的可见性,和委托的作用域,可以在委托的定义上应用任意常见的访问修饰符:public、private、protected等
例如:
public delegate string GetAString();
使用委托:
private delegate string GetAString(); static void Main() { int x=40; GetAString firstStringMethod = new GetAString(x.ToString); Console.WriteLine("String is {0}",firstStringMethod () ); }
由上述代码可以看到,C#的委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法,但是这个方法必须匹配最初定义委托时的签名。
实际上,给委托实例提供圆括号与调用委托类的Invoke()方法完全相同。使用Invoke完成一个委托方法的封送,就类似于使用SendMessage方法来给界面线程发送消息,是一个同步方法。也就是说在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞。
因为firstStringMethod 是一个委托类型的变量,所以C#编译器会用firstStringMethod.Invoke()代替firstStringMethod ()。
firstStringMethod(); firstStringMethod.Invoke();
为了减少输入量,只需要委托实例,就可以只传递地址的名称,即委托推断。
GetAString firstStringMethod = new GetAString(x.ToString); GetAString firstStringMethod = x.ToString;
注意:输入行事不能是x.ToString(),也不能把它传给委托变量。x.ToString表示把方法的地址赋予委托变量。
多播委托:
委托可以包含多个方法,这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。但是,委托的签名必须返回void,否则只能得到委托调用的最后一个方法的结果。
多播委托示例程:
delegate void Delegate_Multicast(int x, int y); Class Class2 { static void Method1(int x, int y) { Console.WriteLine("You r in Method 1"); } static void Method2(int x, int y) { Console.WriteLine("You r in Method 2"); } public static void Main() { Delegate_Multicast func = new Delegate_Multicast(Method1); func += new Delegate_Multicast(Method2); func(1,2); // Method1 and Method2 are called func -= new Delegate_Multicast(Method1); func(2,3); // Only Method2 is called } }
解析:
上面的示例程序分别定义了名为method1 和 method2的两个接受整型参数、返回类型为void的方法。
在Main函数里使用下面的声明创建委托对象:
Delegate_Multicast func = new Delegate_Multicast(Method1);
然后使用+= 来添加委托,使用-=来移除委托。
合并委托:
委托对象的一个用途在于,可以使用 + 运算符将它们分配给一个要成为多路广播委托的委托实例。组合的委托可调用组成它的那两个委托。只有相同类型的委托才可以组合。
- 运算符可用来从组合的委托移除组件委托。
delegate void Del(string s); class TestClass { static void Hello(string s) { System.Console.WriteLine(" Hello, {0}!", s); } static void Goodbye(string s) { System.Console.WriteLine(" Goodbye, {0}!", s); } static void Main() { Del a, b, c, d; // Create the delegate object a that references // the method Hello: a = Hello; // Create the delegate object b that references // the method Goodbye: b = Goodbye; // The two delegates, a and b, are composed to form c: c = a + b; // Remove a from the composed delegate, leaving d, // which calls only the method Goodbye: d = c - a; System.Console.WriteLine("Invoking delegate a:"); a("A"); System.Console.WriteLine("Invoking delegate b:"); b("B"); System.Console.WriteLine("Invoking delegate c:"); c("C"); System.Console.WriteLine("Invoking delegate d:"); d("D"); } } /*------------------------- 输出 Invoking delegate a: Hello, A! Invoking delegate b: Goodbye, B! Invoking delegate c: Hello, C! Goodbye, C! Invoking delegate d: Goodbye, D! ----------------------*/
匿名方法:
到目前为止,要想使用委托工作,方法必须已经存在。但是还有另一种使用委托的方法:即通过匿名方法。匿名方法是用作委托的参数的一段代码。
用匿名方法定义委托的语法与前面的定义并没有区别。但在实例化的时候就有了区别了。
如果使用匿名方法,则不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。
例如,如果创建方法所需的系统开销是不必要的,在委托的位置指定代码块就非常有用。启动新线程即是一个很好的示例。无需为委托创建更多方法,线程类即可创建一个线程并且包含该线程执行的代码。
void StartThread() { System.Threading.Thread t1 = new System.Threading.Thread (delegate() { System.Console.Write("Hello, "); System.Console.WriteLine("World!"); }); t1.Start(); }
委托类型派生自 .NET Framework 中的 Delegate 类。 委托类型是封装的,它们不能派生出其他类,也不能从 Delegate 派生出自定义类。 由于实例化的委托是一个对象,因此可以作为参数传递或分配给一个属性。 这允许方法作为参数接受委托并在稍后调用委托。 这被称为异步回调,是在长进程完成时通知调用方的常用方法。 当以这种方式使用委托时,使用委托的代码不需要知道要使用的实现方法。 功能类似于封装接口提供的功能。
相关文章推荐
- 浅析C#中的委托
- C#深拷贝
- ORA-01000:超出打开游标的最大数 的解决办法(C#)
- 转载(如何学习C#)
- C#操作Excel文件
- .net c# wpf线程使用心得。
- c#中的delegate(委托)和event(事件)
- c#中的delegate(委托)和event(事件)
- C#的面向对象特性之多态
- C# 基础从头来
- C#基础------递归
- C#创建windows服务的步骤
- csharp: SDK:CAPICOM
- C#操作xml文件
- C#基础练习题
- C#chart之PieChart
- C#创建windows程序小分析
- C# windows服务简介
- C#——await与async实现多线程异步编程
- C#——await与async实现多线程异步编程