委托的实现匿名函数和朗姆达表达式

**委托(delegate):一个表示方法的数据类型。间接派生于System.Delegate

委托是一个引用类型,但不必用new来实例化它。直接传递名称,而不是现实实例化。这是c#2.0开始支持的一个新语法,成为委托推断(delegate inference)

 

 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 }

 

**匿名方法:就是没有实际方法声明委托实例,或者说,他们的定义是直接内嵌在代码中的。

 

 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 });  

注意,在任何情况下,参数和返回值类型必须兼容于委托的数据类型。

*匿名方法是允许省略参数列表的,但是返回值类型需要与委托一致。

**系统定义的委托:

System.Func 在.NET 3.5中代表有返回类型的委托

System.Action代表无返回类型的委托。

不能将一个委托类型赋给另一个委托类型的变量,即使类型参数匹配。

*为委托使用可变性[还没理解]

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语句

 

[csharp] view plaincopy
1 BubbleSort(items,  
2                 delegate(int first, int second)  
3             {  
4                 return first < second;  
5             });  

与上述等价的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表达式(满足……条件)


 

  1. BubbleSort(items,  
  2.     (int first, int second)=> first < second );  


**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'

posted @ 2015-08-01 18:00  老皮肉  阅读(1239)  评论(0编辑  收藏  举报