一,什么是委托?
在MSDN中写着:delegate
是一种可用于封装命名或匿名方法的引用类型。 委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。
PS:针对这委托是类型安全和可靠的理解:委托本质是类,是强类型,.net下对象都是类型安全的(类型安全的原因:C#在编译期会检验类型,如果不一致则编辑器生成一个编译时错误)。
参照:http://bbs.csdn.net/topics/330140759
二,那可用于封装命名或匿名方法的引用类型怎么理解?
委托:可以在不同对象之间传递方法,这个方法可以是命名方法,也可以是匿名方法。可以是静态方法,也可以是实例方法。而正是因为传的仅仅是方法名,看不到具体的实现,则这体现了封装的思想,并且委托的实现需要实例,同时证明委托也是引用类型。如下的例子:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace delegateDemo{ class Program { public delegate void delegateInt(); static void Main(string[] args) { Test t = new Test(); //实现静态方法委托,传入方法名即可 delegateInt de = new delegateInt(Test.say); //实现实例委托,传入方法名 delegateInt de2 = new delegateInt(t.say2); de(); de2(); Console.ReadKey(); } } class Test { public static void say() { Console.WriteLine("我是委托"); } public void say2() { Console.WriteLine("我是委托2"); } }}
匿名实现委托
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace delegateDe{ class Program { delegate void delegateNiName(string str); static void Main(string[] args) { delegateNiName DelA = new delegateNiName(Test.say); delegateNiName DelB = delegate(string s) { Console.WriteLine(s); }; delegateNiName DelC = (x) => { Console.WriteLine(x); }; // 实现委托 DelA("我是静态实现委托"); DelB("我是匿名实现委托1"); DelC("我是匿名实现委托2"); Console.ReadKey(); } } class Test { public static void say(string s) { Console.WriteLine(s); } }}
三,delegate,event,Action<T> 和Func<T>又有什么区别:
1》先是event和delegate的区别:
1,事件是一种特殊的委托,或者说是受限制的委托,是委托一种特殊应用,只能施加+=,-=操作符。二者本质上是一个东西。
2,event只允许用add, remove方法来操作,这导致了它不允许在类的外部被直接触发,只能在类的内部适合的时机触发,委托可以在外部被触发。如下例子
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace delegateDiff{ class Test { // 编译代码后,使用 Visual Studio 2010自带的ILDASM.EXE反编译(简称IL),可知道:NET将委托定义为一个密封类,派生自基类System.MulticastDelegate, //并继承了基类的三个方法 public delegate void DelegateTest(); public event DelegateTest EventIn; // 定义委托事件,这个EventIn只有委托的+=,或者-=,这个是一个特殊的委托 public DelegateTest DelegateIn; public void Say() { if (this.EventIn != null) //事件的触发,say方法被下面的main函数调用触发EventIn事件 { this.EventIn(); } if (this.DelegateIn != null) { this.DelegateIn(); } } } class Program { static void EventTest() { Console.WriteLine("haha!我是事件"); } static void DelegateTest() { Console.WriteLine("haha!我是委托"); } static void Main(string[] args) { Test TestIn = new Test(); TestIn.DelegateIn += DelegateTest; TestIn.EventIn += EventTest; //别人触发方法的实现,事件和委托都可以 TestIn.Say(); //委托和事件的区别:委托可以自己触发实现,而事件则会报错 TestIn.DelegateIn(); // TestIn.EventIn(); // 事件触发会报错 Console.ReadKey(); } }}
2》Action<T>和Func<T>,则是.NET默认的委托类型,即是封装好的委托
1.Action<T>泛型Action<T>委托表示引用一个void返回类型的方法。
这个委托类存在16种重载方法。 例如Action<in T1,In T2>调用没有参数的方法
Actionaction = i => Console.WriteLine(i); action("Hello");
2.Func<T>
Func<T>调用带返回类型的方法。有16种重载方法。 例如Func<out TResult>委托类型可以调用带返回类型且无参数的方法,
Func<in T,out TResult>委托类型调用带有4个参数和一个返回类型的方法。
//func和表达式的使用 Expression> ex = (i => i > 0); Func func = ex.Compile(); var Test = func(5); //返回true //Func的定义和调用 Func funcT = (i => { i = "Hello"; Console.WriteLine(i); return false; }); //Func的定义和调用,返回值类型自定义 Func funcT1 = (i => { i = "Hello"; Console.WriteLine(i); return i; }); var Te1 = funcT1("Hello"); //返回输入内容 //Func的无参的时候的使用 Func funcT2 = (() => { Console.WriteLine("Hello"); return false; }); var Te = funcT2(); //返回false //Func的无参的时候的使用,返回值类型自定义 Func funcT3 = (() => { Console.WriteLine("Hello"); return "Hello"; }); var Te3 = funcT3(); //返回输入内容 if (funcT("Hello")) { Console.WriteLine("Hello"); } else { Console.WriteLine("World"); }