程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> 《C#本質論》讀書筆記(12)委托和Lambda表達式

《C#本質論》讀書筆記(12)委托和Lambda表達式

編輯:C#基礎知識


12.1.
委托概述
 

12.1.2 委托的數據類型

為了減少重復代碼數量,可以將比較方法作為參數傳遞給 BubbleSort()方法。此外,為了將方法作為參數傳遞,必須有一個能夠標識方法的數據類型——也就是委托。這裡的委托類型是 ComparisonHandler 。 c# 2.0之前的寫法
  1. class DelegateSample  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             //int[] arr = { 10, 20, 30, 40, 50 };  
  6.             int[] arr = { 50, 40, 30, 20, 10 };  
  7.   
  8.             ConsoleArr(arr);  
  9.   
  10.             ComparisonHandler wx = new ComparisonHandler(DelegateSample.IsTrue);  
  11.             BubbleSort(arr, wx);  
  12.       //C#2.0之前是這麼寫的
  13.       //BubbleSort(arr, new ComparisonHandler(IsTrue));  
  14.   
  15.             ConsoleArr(arr);  
  16.   
  17.             Console.Read();  
  18.         }  
  19.   
  20.         public delegate bool ComparisonHandler(int a, int b);  
  21.   
  22.         public static bool IsTrue(int a, int b)  
  23.         {  
  24.                 return a > b;  
  25.         }  
  26.   
  27.         public static void BubbleSort(int[] items, ComparisonHandler comparisonMethod)  
  28.         {  
  29.             int i;  
  30.             int j;  
  31.             int temp;  
  32.             if (items == null)  
  33.             {  
  34.                 return;  
  35.             }  
  36.             if (comparisonMethod == null)  
  37.             {  
  38.                 throw new ArgumentNullException("comparisonMethod");  
  39.             }  
  40.             for (i = items.Length - 1; i >= 0; i--)  
  41.             {  
  42.                 for (j = 1; j <= i; j++)  
  43.                 {  
  44.                     if (comparisonMethod(items[j - 1], items[j]))  
  45.                     {  
  46.                         temp = items[j - 1];  
  47.                         items[j - 1] = items[j];  
  48.                         items[j] = temp;  
  49.                     }  
  50.                 }  
  51.             }  
  52.         }  
  53.   
  54.         public static void ConsoleArr(int[] arr)  
  55.         {  
  56.             foreach (var item in arr)  
  57.             {  
  58.                 Console.Write(item+",");  
  59.             }  
  60.             Console.WriteLine();  
  61.         }  
  62.     }  


C#2.0以後可以直接調用方法 
  1. public static bool AlphabeticalIsTrue(int a,int b)  
  2.         {  
  3.             int comparison;  
  4.             comparison = (a.ToString().CompareTo(b.ToString()));  
  5.             return comparison > 0;  
  6.         }  
  7.   
  8.   
  9. //C# 2.0以後直接傳遞方法  
  10.             BubbleSort(arr, AlphabeticalIsTrue); 

12.1.3 委托內部機制

第一個屬性屬於 System.Reflection.MethodiInfo 類型,MethodInfo 定義一個特定方法的簽名,其中包括方法的名稱、參數和返回類型。除了 MethodInfo,委托還需要一個對象實例,其中包含了要調用的方法。這正式第二個屬性 Target 的用途。在靜態方法的情況下,Target 對應於類型自身。
  1. // 摘要:   
  2. //     初始化一個委托,該委托對指定的類實例調用指定的實例方法。  
  3. //  
  4. // 參數:   
  5. //   target:  
  6. //     類實例,委托對其調用 method。  
  7. //  
  8. //   method:  
  9. //     委托表示的實例方法的名稱。  
  10. //  
  11. // 異常:   
  12. //   System.ArgumentNullException:  
  13. //     target 為 null。 - 或 - method 為 null。  
  14. //  
  15. //   System.ArgumentException:  
  16. //     綁定到目標方法時出錯。  
  17. [SecuritySafeCritical]  
  18. protected Delegate(object target, string method);  
  19. //  
  20. // 摘要:   
  21. //     初始化一個委托,該委托從指定的類調用指定的靜態方法。  
  22. //  
  23. // 參數:   
  24. //   target:  
  25. //     System.Type,它表示定義 method 的類。  
  26. //  
  27. //   method:  
  28. //     委托表示的靜態方法的名稱。  
  29. //  
  30. // 異常:   
  31. //   System.ArgumentNullException:  
  32. //     target 為 null。 - 或 - method 為 null。  
  33. //  
  34. //   System.ArgumentException:  
  35. //     target 不是 RuntimeType。 請參見 反射中的運行時類型。 - 或 - target 表示開放式泛型類型。  
  36. [SecuritySafeCritical]  
  37. protected Delegate(Type target, string method);  


12.2.
匿名方法
 

傳遞一個匿名方法

  1. class Program 
  2. {  
  3.     public delegate bool ComparisonHandler(int a, int b);  
  4.     static void Main(string[] args)  
  5.     {  
  6.         int i;  
  7.         int[] items = new int[5];  
  8.         ComparisonHandler comparionMethod;  
  9.         for (i = 0; i < items.Length; i++)  
  10.         {  
  11.             Console.WriteLine("Enter an integer:");  
  12.             items[i] = int.Parse(Console.ReadLine());  
  13.         }  
  14.   
  15.        comparionMethod = delegate(int first, int second)   
  16.         {                                                                   
  17.             return first < second;                                    
  18.         };                                                                  
  19.         BubbleSort(items, comparionMethod);                   
  20.   
  21.         for ( i = 0; i < items.Length; i++)  
  22.         {  
  23.             Console.WriteLine(items[i]);  
  24.         }  
  25.   
  26.         Console.Read();  
  27.           
  28.     }  
  29.   
  30.     public static void BubbleSort(int[] items, ComparisonHandler comparisonMethod)  
  31.     {  
  32.         int i;  
  33.         int j;  
  34.         int temp;  
  35.         if (items == null)  
  36.         {  
  37.             return;  
  38.         }  
  39.         if (comparisonMethod == null)  
  40.         {  
  41.             throw new ArgumentNullException("comparisonMethod");  
  42.         }  
  43.         for (i = items.Length - 1; i >= 0; i--)  
  44.         {  
  45.             for (j = 1; j <= i; j++)  
  46.             {  
  47.                 if (comparisonMethod(items[j - 1], items[j]))  
  48.                 {  
  49.                     temp = items[j - 1];  
  50.                     items[j - 1] = items[j];  
  51.                     items[j] = temp;  
  52.                 }  
  53.             }  
  54.         }  
  55.     }  
  56. }  


12.3.
系統定義的委托:Func 和 Action 聲明
 
在.NET3.5(C# 3.0)中,存在一系列名為“Action”和“Func”的泛型委托。System.Func 代表有返回類型的委托,而 System.Action 代表無返回類型的委托。  .NET 委托類型不具備結構的相等性(structural equality)。不能將某個委托類型對象引用轉換為不相關的委托類型,即使這兩個委托類型的形參和返回類型完全一致。例如,這裡就不能將 ComparisonHandler 引用直接賦給一個Func<int,int,bool>變量。遺憾的是,需要結構一致但不相關的委托類型的情況下,為了使用給定的委托,唯一的辦法是創建一個新委托。讓它引用舊委托的 Invoke 方法。假定有一個 ComparisonHandler 變量 c,需要把 c 賦值給 Func<int,int,bool>類型的變量 f ,那麼可以寫成 f = c.Invoke;。 
Invoke說明

公共語言運行時提供 Invoke 每種委托類型,具有相同的簽名與委托的方法。 您不需要顯式調用此方法,從 C#、 Visual Basic 或 Visual c + +,因為編譯器會自動調用。 Invoke 方法就很有用 反射 如果想要查找的委托類型簽名。

https://msdn.microsoft.com/zh-cn/library/system.delegate.aspx


12.4.
語句Lambda
 

1.無參數的語句

即使無參數的語句lambda(代表無輸入參數的委托),也要輸入一對空白的圓括號
  1. static void Main(string[] args)  
  2. {  
  3.     //...  
  4.     Func<string> getUserInput =  
  5.         () =>  
  6.         {  
  7.             string input;  
  8.             do  
  9.             {  
  10.                 input = Console.ReadLine();  
  11.             }  
  12.             while (input.Trim().Length == 0);  
  13.             return input;  
  14.         };  
  15.     //...  
  16. }  
圓括號規則的一個例外是,當編譯器能推斷出數據類型,而且只有一個參數的時候。語句Lambda可以不帶圓括號。

2.只有一個參數的語句

  1. IEnumerable<Process> processes = Process.GetProcesses()  
  2. .Where(process => { return process.WorkingSet64 > 100000000; });  
Where() 返回的是對物理內存占用超過 1GB 的進程的一個查詢
12.5.
表達式Lambda
 
語句Lambda含有一個語句塊,所以可以包含零個或者更多的語句,表達式Lambda比語句Lambda更進一步。語句Lambda的代碼塊都只由一個return語句構成。其實在這種lambda塊中,唯一需要就是准備返回的表達式。其他可以省略。使用一個表達式Lambda來傳遞委托
  1. BubbleSort(items, (first, second) => first > second);  
語句lambda的比較

  1. BubbleSort(items, (first, second) => 
  2.     {
  3.         return first > second;
  4.     }
  5. );  


12.6.
表達式樹
 









  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved