**委托(delegate):一个表示方法的数据类型。间接派生于System.Delegate
委托是一个引用类型,但不必用new来实例化它。直接传递名称,而不是现实实例化。这是c#2.0开始支持的一个新语法,成为委托推断(delegate inference)
namespace delegateEx
{
//委托声明
public delegate bool ComparisonHandler(int first,int second);
public static class DelegateSample
{ //
public static void BubbleSort(int[] items, ComparisonHandler comparisonMethod)
{
int i;
int j;
int temp;
if (items == null)
{
return;
}
if (comparisonMethod == null)
{
throw new ArgumentNullException("comparisonMethod");
}
for (i = items.Length - 1; i >= 0; i--)
{
for (j = 1; j <= i; j++)
{
//用委托实例
if (comparisonMethod(items[j - 1], items[j]))
{
temp = items[j - 1];
items[j - 1] = items[j];
items[j] = temp;
}
}
}
}
//匹配委托的参数GreaterThan(int first, int second)
public static bool GreaterThan(int first, int second)
{
return first > second;
}
}
class Program
{
static void Main(string[] args)
{
int[] items = new int[100];
Random random = new Random();
for (int i = 0; i < items.Length; i++)
{
items[i] = random.Next(1,100);
}
//将委托实例作为参数传递
DelegateSample.BubbleSort(items, DelegateSample.GreaterThan);
for (int i = 0; i < items.Length; i++)
{
Console.Write(" {0}",items[i]);
}
Console.ReadKey();
}
}
}
**匿名方法:就是没有实际方法声明委托实例,或者说,他们的定义是直接内嵌在代码中的。
static void Main(string[] args)
{
int[] items = new int[5];
Random random = new Random();
ComparisonHandler comparisonMethod;
for (int i = 0; i < items.Length; i++)
{
items[i] = random.Next(1, 100);
}
//委托的定义直接内嵌在代码中。
comparisonMethod = delegate(int first, int second)
{
return first < second;
};
BubbleSort(items,comparisonMethod);
for (int i = 0; i < items.Length; i++)
{
Console.Write(" {0}", items[i]);
}
Console.ReadKey();
}
或者使用更直接的方法:
BubbleSort(items,
delegate(int first, int second)
{
return first < second;
});
注意,在任何情况下,参数和返回值类型必须兼容于委托的数据类型。
*匿名方法是允许省略参数列表的,但是返回值类型需要与委托一致。
**系统定义的委托:
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语句
BubbleSort(items,
delegate(int first, int second)
{
return first < second;
});
与上述等价的
Lamda语句(用于)
BubbleSort(items,
(int first, int second)=>
{
return first < second;
}
);
*省略参数类型:通常,只要编译器能推断出参数类型,或者能将参数类型隐式转换成期望的数据类型,语句Lamda就不需要参数类型。如果要制定类型,那么制定的类型必须和委托类型完全匹配。只要Lamda语句包含了一个类型,则所有的类型都要加上。
BubbleSort(items,
(first,second)=>
{
return first < second;
}
);
*c#要求用一对圆括号来封闭Lamda表达式的参数类表,不管是否指定了这些参数的数据类型。圆括号的另外一个规则是,当编译器能推断出数据类型,而且只有一个输入参数的时候,语句Lamda可以不带圆括号。
Func<string> getUserInput=
()=>
{
string input;;
do
{ input=Console.ReadLine();}
while(input.Trim()==0);
return input;
}
*Lamda表达式(满足……条件)
BubbleSort(items,
(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'