**委託(delegate):一個表示方法的數據類型。間接派生於System.Delegateexpress
委託是一個引用類型,但沒必要用new來實例化它。直接傳遞名稱,而不是現實實例化。這是c#2.0開始支持的一個新語法,成爲委託推斷(delegate inference)c#
1 namespace delegateEx 2 { 3 //委託聲明 4 public delegate bool ComparisonHandler(int first,int second); 5 6 public static class DelegateSample 7 { // 8 public static void BubbleSort(int[] items, ComparisonHandler comparisonMethod) 9 { 10 int i; 11 int j; 12 int temp; 13 if (items == null) 14 { 15 return; 16 } 17 if (comparisonMethod == null) 18 { 19 throw new ArgumentNullException("comparisonMethod"); 20 } 21 22 for (i = items.Length - 1; i >= 0; i--) 23 { 24 for (j = 1; j <= i; j++) 25 { 26 //用委託實例 27 if (comparisonMethod(items[j - 1], items[j])) 28 { 29 temp = items[j - 1]; 30 items[j - 1] = items[j]; 31 items[j] = temp; 32 } 33 } 34 } 35 } 36 //匹配委託的參數GreaterThan(int first, int second) 37 public static bool GreaterThan(int first, int second) 38 { 39 return first > second; 40 } 41 } 42 class Program 43 { 44 static void Main(string[] args) 45 { 46 int[] items = new int[100]; 47 Random random = new Random(); 48 for (int i = 0; i < items.Length; i++) 49 { 50 items[i] = random.Next(1,100); 51 } 52 //將委託實例做爲參數傳遞 53 DelegateSample.BubbleSort(items,DelegateSample.GreaterThan); 54 55 for (int i = 0; i < items.Length; i++) 56 { 57 Console.Write(" {0}",items[i]); 58 } 59 Console.ReadKey(); 60 } 61 } 62 }
**匿名方法:就是沒有實際方法聲明委託實例,或者說,他們的定義是直接內嵌在代碼中的。dom
1 static void Main(string[] args) 2 { 3 int[] items = new int[5]; 4 Random random = new Random(); 5 ComparisonHandler comparisonMethod; 6 7 for (int i = 0; i < items.Length; i++) 8 { 9 items[i] = random.Next(1, 100); 10 } 11 //委託的定義直接內嵌在代碼中。 12 comparisonMethod = delegate(int first, int second) 13 { 14 return first < second; 15 }; 16 BubbleSort(items,comparisonMethod); 17 18 for (int i = 0; i < items.Length; i++) 19 { 20 Console.Write(" {0}", items[i]); 21 } 22 Console.ReadKey(); 23 }
或者使用更直接的方法:函數
1 BubbleSort(items, 2 delegate(int first, int second) 3 { 4 return first < second; 5 });
注意,在任何狀況下,參數和返回值類型必須兼容於委託的數據類型。this
*匿名方法是容許省略參數列表的,可是返回值類型須要與委託一致。spa
**系統定義的委託:.net
System.Func 在.NET 3.5中表明有返回類型的委託code
System.Action表明無返回類型的委託。blog
不能將一個委託類型賦給另外一個委託類型的變量,即便類型參數匹配。ip
*爲委託使用可變性[還沒理解]
Action<object> broadAction=delegate(object data) { Console.WriteLine(data); } Action<string> narrowAction=broadAction; Func<string>narrowFunction=delegate() { return Console.WriteLine(); }; Func<object> broadFunction=narrowAction; Func<object ,string >func1= degate(object data) { return data.ToString(); }; Func<string,object>func2=fun1;
**Lamda表達式 (關鍵字=>) :分爲Lamda表達式和Lamda語句
與上述等價的Lamda語句(用於)
1 BubbleSort(items, 2 (int first, int second)=> 3 { 4 return first < second; 5 } 6 );
*省略參數類型:一般,只要編譯器能推斷出參數類型,或者能將參數類型隱式轉換成指望的數據類型,語句Lamda就不須要參數類型。若是要制定類型,那麼制定的類型必須和委託類型徹底匹配。只要Lamda語句包含了一個類型,則全部的類型都要加上。
1 BubbleSort(items, 2 (first,second)=> 3 { 4 return first < second; 5 } 6 );
*c#要求用一對圓括號來封閉Lamda表達式的參數類表,無論是否指定了這些參數的數據類型。圓括號的另一個規則是,當編譯器能推斷出數據類型,並且只有一個輸入參數的時候,語句Lamda能夠不帶圓括號。
Func<string> getUserInput=
()=>
{
string input;;
do
{ input=Console.ReadLine();}
while(input.Trim()==0);
return input;
}
*Lamda表達式(知足……條件)
**Lamda表達式自己沒有類型
因此 . 運算符不會被編譯,調用Object的方法也不行。
不能出如今is的左側
Lamda表達式一旦被賦值或者轉型,就會有Lamda表達式的類型這種非正式的說法
不能賦值給隱式類型的變量
若是目的在Lamda表達式的外部,c#就不容許在匿名函數內部使用跳轉語句(break,continue,goto)
*外部變量:在Lamda表達式(包括參數)的外部聲明,可是Lamda表達式的內部捕捉(訪問)的局部變量稱爲外部變量。this也是一個外部變量。
int comparisonCount=0;
...
BubbleSort(item,
(int first ,int second)=>
{
comparisonCount++;
return first<second;
}
);
Console.WriteLine(comparisonCount);
**表達式樹[不理解]
「解釋」是c#引入表達式樹(expression trees)這一律唸的重要動機。若是一種Lamda表達式表明的是與表達式有關的數據,而不是編譯好的代碼,這中Lamda表達式就是表達式樹。因爲表達式樹表明的是數據而非編譯好的代碼,因此能夠把數據轉換成一種替代格式。例如,轉換成SQL代碼。
persons.Where(person=>person.Name.ToUpper()=="INIGO MONTOYA")
select *from Person where upper(Name)='INIGO MONTOYA'