C#2.0中,匿名方法是通过delegate来实现的,可以看成是delegate功能的一种扩展。
delegate就如同一个盒子的模型,可以照模型复制一个盒子(产生对象),打上标签(对象名),装进东西(符合签名的方法),然后用它做点什么.
C#早期版本中delegate的用法:
在C# 1.X中,只有一种方法可以实例化delegate,如同实例化对象一样,将一个符合delegate签名的方法作为参数传给delegate:
在List1类中,Sample委托的实例f引用了静态方法Plus(int x, int y).在C#2.0中,可以用匿名方法来实例化一个delegate
匿名方法
在C# 2.0中的匿名方法示例如下:
delegate int Sample(int x, int y);
class List2
{
static int Plus(int x, int y)
{
return x + y;
}
static string myField = "Hello";
public static void Main()
{
Sample f = new Sample(List2.Plus);
int result = f(2, 3);
System.Console.WriteLine(result);
string refToMyField = List2.myField;
System.Console.WriteLine(refToMyField);
string variable = "polarlights";
System.Console.WriteLine(variable);
Sample anonymousFunction = delegate(int x, int y) { return x * y; }; //匿名方法
int dynamicResult = anonymousFunction(3, 4);
System.Console.WriteLine(dynamicResult);
}
}
需要注意的是:
1.在C#2.0中,delegate关键字有了新的意义,当编译器发现它出现在一个方法体内时(上例出现在Main()方法内),编译器会期望它后面出现一个匿名方法体(上例中是{return x*y})。
2.可以将一个匿名方法赋给一个delegate实例(上例中赋给了Sample的实例anonymousFunction )
3.可以这样理解为何称其为匿名方法:这个方法定义在一个现有方法的内部而且自己没有名字。我们可以调用它,因为一个delegate的实例引用了它
另外,在匿名方法 Sample anonymousFunction = delegate(int x, int y) { return x * y; };中,只指定了参数类型,没有指定返回值的类型,因为编译器知道在Sample委托中定义的类型是int型,如果尝试将其改为:Sample anonymousFunction = delegate(int x, int y) { return "123"; };则编译器会提示"无法将匿名方法块转换为委托类型“Sample”,原因是块中的某些返回类型不能隐式转换为委托返回类型" 。
匿名方法中的参数
1.匿名方法可以接受实参,但什么都不做:
2.在匿名方法声明中可以将形参忽略,虽然其对应的delegate定义是有参数的:
delegate int Sample(int x, int y);
class List4
public static void Main()
{
Sample anonymousFunction = delegate //忽略了参数
{
return System.DateTime.Now.Millisecond; // 表示当前时间的毫秒部分
};
int dynamicResult = anonymousFunction(3, 4);
System.Console.WriteLine(dynamicResult); // 将显示当前时间的毫秒部分
}
}
3.在匿名方法声明中 ,要么使其形参为空,如同上例所示,要么使其形参完整,符合与其对应的delegate的定义。否则会出编译错误:
delegate int Sample(int x, int y);
class List5
public static void Main()
{
Sample anonymousFunction = delegate(int x)
{
return x * 2;
};
}
}
编译器会提示"法将匿名方法块转换为委托类型“Sample”,原因是指定块的参数类型与委托参数类型不匹配"
匿名方法与泛型:
如下所示,匿名方法也可以声明泛型参数<T>.一个带泛型参数的匿名方法可以赋给一个同类型的delegate实例,只需确保其符合delegate签名即可
using System;
class List6<T>
{
delegate void DelegateType(T t);
internal void UneMethode(T t)
{
DelegateType delegateInstance = delegate(T arg) { Console.WriteLine( "Hello args:{0}", arg.ToString()); };
delegateInstance(t);
}
}
class Program
{
static void Main()
{
List6<double> inst = new List6<double>();
inst.UneMethode(5.5);
Console.ReadKey();
}
}
该例中定义了一个泛型类List6,一个泛型委托DelegateType和一个泛型匿名方法(没有名字的东东),然后在Main()方法中实例化泛型类List6,类型指定为double型,将double型实参5.5传入内部泛型实例方法UneMethode中,该方法将一个泛型匿名方法赋给一个泛型委托DelegateType的实例,并用该实例调用泛型匿名方法。
适用匿名方法的情形:
个人认为,在需要调用一些小方法的时候,比较适合用匿名方法.比如下面的例子,在线程开始时调用匿名方法,显示当前线程哈希值和相关信息:
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread thread = new Thread(delegate()
//这里调用的是Thread类构造函数第一形态--ParameterizedThreadStart 委托,匿名方法代之
//.NET Framework 2.0新增,详见MSDN 2005类库参考
{
Console.WriteLine("ThreadHashCode:{0} Hello", Thread.CurrentThread.GetHashCode());
});
thread.Start();
Console.WriteLine("ThreadHashCode:{0} polarlights", Thread.CurrentThread.GetHashCode());
Console.ReadKey();
}
}
亦可用于事件的调用: