1.委托
C#的委托相当于C/C++中的函数指针。函数指针用指针获取一个函数的入口地址,实现对函数的操作。
委托与C/C++中的函数指针不同在于,委托是面向对象的,是引用类型,对委托的使用要先定义后实例化,最后才能调用。并且委托是类型安全的,它定义了返回类型和参数的类型,而在C/C++中,函数指针只是一个指向内存位置的指针,它不是类型安全的,我们无法判断这个指针实际指向什么,所以参数和返回类型等项就无法知道了。
定义委托
使用关键字delegate。语法类似于方法的定义,但没有方法体,定义的前面加上关键字delegate。
例如:定义一个委托:delegate void IntMethod(int x);
在这个示例中,定义了一个委托IntMethod,并指定该委托的每个实例都可以包含一个方法的引用,该方法带有一个int参数,返回类型为void。
如果要定义一个委托TwoLongOp,该委托表示的方法有两个long类型的参数,返回类型为double,则可以这样定义:delegate double TwoLongOp(long first,long second);
delegate string GetString();//该委托表示的方法没有参数,返回string类型。
定义委托基本上是定义一个新类,可以在定义类的任何相同地方定义委托。也就是说可以在一个类的内部定义,也可以在外部定义,还可以在命名空间中把委托定义为顶层对象。
可以在委托的定义上应用访问修饰符:public,protected,private等,用来限定委托的作用域。例如:public delegate void IntMethod(int x);
实例化,调用
1 private delegate string GetString(int x);//定义委托 2 static void Main(string[] args) 3 { 4 GetString strMed = new GetString(StringMethod);//对委托进行实例化,并进行初始化 5 Console.WriteLine(strMed(555));//调用委托 6 Console.ReadKey(); 7 } 8 private static string StringMethod(int x) 9 { 10 return x.ToString(); 11 }
注意,在C#中,委托总是接受一个参数的构造函数,这个参数就是委托引用的方法,这个方法必须匹配委托定义时的签名。本例中委托定义时,返回类型为string,参数类型为int,所以初始化变量strMed时的方法StringMethod也必须与之一致。
类有两个不同的术语,“类”表示较广泛的定义,对象表示类的实例。但委托只有一个术语,在创建委托的实例时,所创建的委托实例仍称委托。
还可以直接把委托所引用的方法直接赋值给委托类型的变量(委托推断),例: GetString strMed =StringMethod;
Action<T>和Func<T>委托
进一步简化了委托的定义,而不用显式声明自定义委托。
泛型Action<T>委托表示引用一个void返回类型的方法,这个委托类存在不同的变体,最多可传递16种不同的参数类型。没有泛型参数的Action类调用没有参数的方法。
public delegate void Action() public delegate void Action<in T>(T obj)
......
1 static void Main(string[] args) 2 { 3 Action<string> messageTarget; 4 messageTarget = GetAStr; 5 messageTarget("Action<T> Demo!"); 6 Console.ReadKey(); 7 } 8 private static void GetAStr(string obj) 9 { 10 Console.WriteLine(obj); 11 }
Func<T>允许调用带返回类型的方法,与Action<T>类似,也定义了不同的变体,最多也可传递16种不同的参数类型和一个返回类型。
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T arg)
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1,T2 arg2) ......
1 public static void Main() 2 { 3 Func<string, int, string[]> extractMethod = ExtractWords;//最后一个是返回值的类型,前面的都是参数的类型。 4 string str = "helloawordaFunc"; 5 foreach (string word in extractMethod(str, 5)) 6 Console.WriteLine(word); 7 } 8 private static string[] ExtractWords(string phrase, int limit) 9 { 10 char[] delimiters = new char[] { ‘a‘ }; 11 if (limit > 0) 12 return phrase.Split(delimiters, limit); 13 else 14 return phrase.Split(delimiters); 15 }
多播委托
一次委托调用多个方法,通过+和-运算符实现多播的增加或减少。多播委托包含已分配委托的列表。在调用多播委托时,它会按顺序调用列表中的委托。只能合并相同类型的委托。
1 static void Main(string[] args) 2 { 3 Action del = D1; 4 del += D2; 5 del += D3; 6 del(); 7 Console.WriteLine("------------------"); 8 del -= D2; 9 del(); 10 Console.ReadKey(); 11 } 12 private static void D1() 13 { 14 Console.WriteLine("I am D1"); 15 } 16 private static void D2() 17 { 18 Console.WriteLine("I am D2"); 19 } 20 private static void D3() 21 { 22 Console.WriteLine("I am D3"); 23 }
msdn上的例子:
1 static void Hello(string s) 2 { 3 System.Console.WriteLine(" Hello, {0}!", s); 4 } 5 static void Goodbye(string s) 6 { 7 System.Console.WriteLine(" Goodbye, {0}!", s); 8 } 9 static void Main() 10 { 11 12 CustomDel hiDel, byeDel, multiDel, multiMinusHiDel; 13 hiDel = Hello; 14 15 byeDel = Goodbye; 16 17 multiDel = hiDel + byeDel; 18 19 multiMinusHiDel = multiDel - hiDel; 20 21 Console.WriteLine("Invoking delegate hiDel:"); 22 hiDel("A"); 23 Console.WriteLine("Invoking delegate byeDel:"); 24 byeDel("B"); 25 Console.WriteLine("Invoking delegate multiDel:"); 26 multiDel("C"); 27 Console.WriteLine("Invoking delegate multiMinusHiDel:"); 28 multiMinusHiDel("D"); 29 }
Lamada表达式和事件将在下篇中介绍。。。。