C# Func<>委托


   委托是一種類型,由關鍵字delegate聲明。確切的說,委托是一種可用於封裝命名或者匿名方法的引用類型。  它類似於 C++ 中的函數指針,而且是類型安全和可靠的。

  委托類型的聲明與方法簽名相似,有一個返回值和任意數目任意類型的參數。必須使用具有兼容返回類型和輸入參數的方法或 lambda 表達式實例化委托。下面給出了委托聲明及實例化的示例代碼:

原先我們定義delegate

[csharp]  view plain  copy
 
 print ?
  1. // 委托聲明 -- 定義一個簽名:  
  2. delegate double MathAction(double num);  
  3. class DelegateTest  
  4. {  
  5.     // 符合委托聲明的常規方法  
  6.     static double Double(double input)  
  7.     {  
  8.         return input * 2;  
  9.     }  
  10.    
  11.     static void Main()  
  12.     {  
  13.       // 使用一個命名方法實例化委托類型  
  14.         MathAction ma = Double;  
  15.    
  16.         // 調用委托實例  
  17.         double multByTwo = ma(4.5);  
  18.         Console.WriteLine(multByTwo);  
  19.    
  20.      // 再用匿名方法來實例化委托類型  
  21.         MathAction ma2 = delegate(double input)  
  22.         {  
  23.             return input * input;  
  24.         };  
  25.    
  26.         double square = ma2(5);  
  27.         Console.WriteLine(square);  
  28.    
  29.       // 最后用Lambda表達式來實例化委托類型  
  30.         MathAction ma3 = s => s * s * s;  
  31.         double cube = ma3(4.375);  
  32.    
  33.         Console.WriteLine(cube);  
  34.     }  
  35. }  

 

.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<>特性的結合,可以看出他們帶給代碼多么大的改變,不僅讓我們的代碼更加簡潔,更讓我們的代碼執行起來更加高效靈活。

 

三種委托寫法對比

 

[csharp]  view plain  copy
 
 print ?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.    
  6. namespace func  
  7. {  
  8. //委托聲明 -- 定義一個簽名:  
  9. delegate double MathAction(double num);  
  10. public class Program  
  11. {  
  12. // 符合委托聲明的常規方法  
  13. static double Double(double input)  
  14. {  
  15. return input * 2;  
  16. }  
  17.    
  18. static void Main(string[] args)  
  19. {  
  20. // 使用一個命名方法實例化委托類型  
  21. /* 
  22.  * 寫法一,需要寫出專門委托的函數,還需要自定義委托 
  23.  **/  
  24. MathAction ma = Double;//注意這里千萬不可有Double(),否則就成了一個返回類型,是報錯的,這里是制定函數的地址,給定的是函數的地址  
  25.    
  26. //調用委托  
  27. double result1 = ma(4.5);  
  28.    
  29. //使用系統自定義委托實例化委托類型  
  30. /* 
  31.  * 寫法二,需要寫出專門委托的函數,不需要自定義委托,使用系統委托 
  32.  **/  
  33. Func<double,double> func = Double;  
  34.    
  35. //調用委托  
  36. double result2 = func(4.5);  
  37.    
  38. //系統委托使用lamdba進行傳遞參數  
  39. /* 
  40.  * 寫法三,不需要寫出專門委托的函數,還需要自定義委托 
  41.  **/  
  42. Func<doubledouble> result = s=> s * 2;//寫法還可以換成lamdba語句塊,適應多個參數的寫法  
  43.    
  44. double result3=result(4.5);  
  45.    
  46. Func<double,double> result4 = s =>  
  47. {  
  48. return s * 2;  
  49. };  
  50.    
  51. Console.WriteLine(result1);  
  52. Console.WriteLine(result3);  
  53. Console.WriteLine(result2);  
  54. Console.WriteLine(result4(4.5));  
  55. }   
  56. }  
  57.    
  58. }  

效果圖

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM