`
javasalatu
  • 浏览: 723825 次
  • 性别: Icon_minigender_2
  • 来自: 北京
博客专栏
96df99eb-e89d-3228-9c8e-967fc745ec52
程序员的自我经营之道
浏览量:7704
文章分类
社区版块
存档分类
最新评论

委托,匿名方法,λ 表达式

 
阅读更多

1、委托:委托本质上就是函数指针,但由于指针过于灵活,因此在很多语言中都采用了更加安全的替代类型,比如Delphi的对象方法和C#的委托.委托使得方法可以做为参数进行传递,极大的方便了程序的处理(事件本质上就是委托,是委托的一种典型应用)。使用委托的最大好处一是可以实现算法上的分离,二是可以实现一定程度上的动态联编(即面向对象中的所谓多态),对于算法上的分离,在面向对象的模式设计中,策略模式是比较典型的,其实我们使用委托照样可以在一定程度上模仿其功能,实际上使用策略模式在很多时候还不如委托来得简单有效,而且在性能上也比委托差些。由于委托本身也是一种规范和标准,因此在这种层面上和抽象类,接口一样具有多态性。当然,委托的这种多态性也必须遵循编程语言的继承规范:子类实例可以赋给父类变量,反之则不允许。根据这种规范,站在委托的角度,委托具有返回值协变,参数抗变的特性。即实际委托调用的返回值只能是委托定义的返回值类型的子类,实际调用方法的参数必须是委托定义中的参数的父类。

如:public delegateA Compare(Type1 v);

实际调用的方法:public B CompareInstance(Type2 v).根据继承规范,Type2必须是Type1的父类,而B必须是A的子类.

2、匿名方法:在给委托变量实例化的时候,一般是提供一个有名的方法,如:Compare _compare=CompareInstance;但现在C#提供了一种匿名方法,匿名方法是一个代码块,本质上与命名方法没有什区别,但与命名方法相比,提供了如下两个便利:1是书写上,使得委托变量可以与实例化方法在一起,这样有利于理解;2是匿名方法可以访问匿名方法代码块以外的变量,这点上相对于命名方法要灵活很多,这是优点,也是缺点,缺点是其破坏了代码的封装性,当然,你把匿名方法与其所在的代码模块看作是一个整体(如果从逻辑上来讲也确实是个整体),那么这个缺点就无所谓了。下面是简单的例子:

int theTest=0;

Compare _compare = delegate(int v){

theTest ++;

}

_compare(2);//调用.

匿名方法使用上的限制主要是程序控制方面的,比如不能跳转到匿名方法块外部,也不能从外部跳转到匿名方法块内部等。由于这种匿名代码块并不能复用,因此我觉得匿名方法的实际应用价值并不大,何况还可以用λ表达式替代。

3、λ表达式:λ表达式的作用其实跟匿名方法没什么区别,可以将λ表达式理解成匿名方法的一种简洁表达方式。

匿名方法和λ表达式的引入,主要作用在于可以使得程序的表达更加简洁,但把这两个东西作为C#语言一个新的特征就有那么一点王婆卖瓜的味道了.其实所谓的范型、匿名方法等很多所谓的C#的新东西都是从C++中拿来重新包装一下而已,思想上并没有本质的进步(题外话:我们中国程序员很多时候都是被这种似是而非的新技术驱赶着跑)。

下面是一个简单的测试例子:

private void button1_Click(object sender, EventArgs e)
{

//Teacher是一个类,包含部门id和姓名两个字段.
var teachers = TestDataMgt.GetTeachers();//获取一个Teacher列表.
//一般方法(委托的典型调用方式),Select需要一个委托参数,该委托的定义:

//Func<TSource,TResult>(TSource obj)
//var depts2 = teachers.Select(new Func<Teacher,int>(FuncB)).Distinct();
#region 使用匿名方法调用.
//Func<Teacher, int> bb = delegate(Teacher T)
//{
// return T._deptId;
//};
//var depts2 = teachers.Select(bb).Distinct();
#endregion

//使用λ表达式,非简洁方式

//var depts2 = teachers.Select((T) => { return T._deptId; }).Distinct();
//等价于
var depts2 = teachers.Select(T=>T._deptId).Distinct();
foreach (var el in depts2)
{
this.richTextBox2.Text += el.ToString() + "/r/n";
}
}
private int FuncB(Teacher obj)
{
return obj._deptId;
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics