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表達式和事件將在下篇中介紹。。。。