在建议36中,我们创建了这样的一个示例程序:
static void Main(string[]args)
{
Func<int,int,int>add=Add;
Action<string>print=Print;
print(add(1,2).ToString());
}
static int Add(int i,int j)
{
return i+j;
}
static void Print(string msg)
{
Console.WriteLine(msg);
}
实际上要完成相同的功能,还有多种编码方式。先来看一个最中规中矩的,同时也是最烦琐的写法:
static void Main(string[]args)
{
Func<int,int,int>add=new Func<int,int,int>(Add);
Action<string>print=new Action<string>(Print);
print(add(1,2).ToString());
}
static int Add(int i,int j)
{
return i+j;
}
static void Print(string msg)
{
Console.WriteLine(msg);
}
注意 上面的语法虽然烦琐,但是我们可以从中加深对委托本质的认识:委托也是一种类型,跟任何FCL中的引用类型没有差别。
从以上写法中注意到:Add方法和Print方法实际上都只有一条语句,因此,使用匿名方法也许是一种更好的选择:
Func<int,int,int>add=new Func<int,int,int>(delegate(int i,int j)
{
return i+j;
});
Action<string>print=new Action<string>(delegate(string msg)
{
Console.WriteLine(msg);
});
print(add(1,2).ToString());
使用匿名方法以后,我们不需要在Main方法外部声明两个方法了,可以直接在Main这个工作方法中完成所有的代码编写,而且不会影响代码清晰性。实际上,所有代码行数不超过3行的方法(条件是它不被重用),我们都建议采用这种方式来编写。上面版本的改进版是:
Func<int,int,int>add=delegate(int i,int j)
{
return i+j;
};
Action<string>print=delegate(string msg)
{
Console.WriteLine(msg);
};
print(add(1,2).ToString());
以上代码看上去更简化了,不过,最终极的改进是使用Lambda表达式:
Func<int,int,int>add=(i,j)=>
{
return i+j;
};
Action<string>print=(msg)=>
{
Console.WriteLine(msg);
};
print(add(1,2).ToString());
Lambda表达式操作符“=>”的左侧是方法的参数,右侧是方法体,其本质是匿名方法。实际上,经过编译后Lambda表达式就是一个匿名方法。我们应该在实际的编码工作中熟练运用它,避免写出烦琐且不美观的代码。
下面以List<T>的Find为例,让我们最后感受一下Lambda表达式在简化代码上的威力:
//第一种写法
return this.Find(new Predicate<Student>(delegate(Student target)
{
if(target.Name==name)
{
return true;
}
else
{
return false;
}
}));
//第二种写法
//return this.Find(new Predicate<Student>((target)=>
//{
//if(target.Name==name)
//{
//return true;
//}
//else
//{
//return false;
//}
//}));
//第三种写法
//return this.Find((target)=>
//{
//if(target.Name==name)
//{
//return true;
//}
//else
//{
//return false;
//}
//});
//第四种写法
//return this.Find(target=>target.Name==name);