委托是一種類型,由關鍵字delegate聲明。確切的說,委托是一種可用於封裝命名或者匿名方法的引用類型。 它類似於 C++ 中的函數指針,而且是類型安全和可靠的。
委托類型的聲明與方法簽名相似,有一個返回值和任意數目任意類型的參數。必須使用具有兼容返回類型和輸入參數的方法或 lambda 表達式實例化委托。下面給出了委托聲明及實例化的示例代碼:
原先我們定義delegate
在.NETFramework 3.5中,提供了兩類通用的delegate。
如果方法有返回值,則使用Func,或者Func<>
如果方法沒有返回值,則使用Action,或者Action<>
Func<T,TR>(T arg)
T
此委托封裝的方法的參數類型。
TR
此委托封裝的方法的返回值類型。
參數
- arg
- 類型 T
- 此委托封裝的方法的參數。
在使用 Func<T,TResult>委托時,不必顯式定義一個封裝只有一個參數的方法的委托。以下示例簡化了此代碼,它所用的方法是實例化 Func<T, TResult>委托,而不是顯式定義一個新委托並將命名方法分配給該委托。
使用Func<>委托,我們這樣寫
1 using System; 2 3 public class GenericFunc 4 { 5 public static void Main() 6 { 7 // 依舊是用命名方法實例化委托類型 8 Func<string, string> convertMethod = UppercaseString; 9 string name = "Dakota"; 10 // 依舊是通過委托實例調用該方法 11 Console.WriteLine(convertMethod(name)); 12 } 13 14 private static string UppercaseString(string inputString) 15 { 16 return inputString.ToUpper(); 17 } 18 }
您也可以按照以下示例所演示的那樣在 C# 中將 Func<T, TResult> 委托與匿名方法一起使用。
1 using System; 2 3 public class Anonymous 4 { 5 public static void Main() 6 { 7 Func<string, string> convert = delegate(string s) 8 { return s.ToUpper();}; 9 10 string name = "Dakota"; 11 Console.WriteLine(convert(name)); 12 } 13 }
您還可以按照以下示例所演示的那樣將 lambda 表達式分配給 Func<T, TResult> 委托。
1 using System; 2 3 public class LambdaExpression 4 { 5 public static void Main() 6 { 7 Func<string, string> convert = s => s.ToUpper(); 8 9 string name = "Dakota"; 10 Console.WriteLine(convert(name)); 11 } 12 }
Lambda 表達式的基礎類型是泛型 Func 委托之一。 這樣能以參數形式傳遞 lambda 表達式,而不用顯式將其分配給委托。 尤其是,因為 System.Linq 命名空間中許多類型方法具有 Func<T, TResult> 參數,因此可以給這些方法傳遞 lambda 表達式,而不用顯式實例化 Func<T, TResult> 委托。
Func委托是system下的全局函數,不用我們自定,系統自定義的,供我們使用,帶有多個重載.
這里我們除了使用Func委托外,還是用了Labdab表達式.這里我再談談這個表達式.
Lambda表達式的基礎類型是泛型 Func委托之一。 這樣能以參數形式傳遞 lambda表達式,而不用顯式將其分配給委托。 尤其是,因為 System.Linq命名空間中許多類型方法具有Func<T, TResult>參數,因此可以給這些方法傳遞 lambda表達式,而不用顯式實例化 Func<T, TResult>委托。
如果前面的解析看的不是很清楚,相信最后這個實例能夠讓你更加明白Func委托是多么有意思。
下面的示例演示如何聲明和使用 Func<T, TResult> 委托。 此示例聲明一個 Func<T, TResult> 變量,並為其分配了一個將字符串中的字符轉換為大寫的 lambda 表達式。 隨后將封裝此方法的委托傳遞給 Enumerable.Select方法,以將字符串數組中的字符串更改為大寫。
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 6 static class Func 7 { 8 static void Main(string[] args) 9 { 10 // 聲明了一個Func委托類型的變量selector並用Lambda表達式進行實例化 11 // 這個Lambda表達式將用來獲取一個字符串並將這個字符串轉化為大寫並返回 12 Func<string, string> selector = str => str.ToUpper(); 13 14 // 創建一個字符串數組 15 string[] words = { "orange", "apple", "Article", "elephant" }; 16 // 依次遍歷這個字符串數組並調用委托實例selector進行處理 17 IEnumerable<String> aWords = words.Select(selector); 18 19 // 輸出結果到控制台 20 foreach (String word in aWords) 21 Console.WriteLine(word); 22 } 23 } 24 /* 25 This code example produces the following output: 26 27 ORANGE 28 APPLE 29 ARTICLE 30 ELEPHANT 31 */
通過委托和Lambda表達式及Func<>特性的結合,可以看出他們帶給代碼多么大的改變,不僅讓我們的代碼更加簡潔,更讓我們的代碼執行起來更加高效靈活。
三種委托寫法對比
效果圖

同樣的輸出效果,但是編寫代碼的質量確有不同。Func的委托中,它簡化了我們自己定義委托帶來的繁瑣,同時它更好的結合了Lamdba的使用,減少了自定義函數的作用,同時也是有缺點的,就是錯誤的出現不容易發現是那里。如果不是對這個很熟悉,很容易造成出現問題,如從着手錯誤的源泉。匿名函數的寫法解決的這個問題。但是匿名函數卻沒有Lamdba簡便。Action委托的使用與Func雷同。

