一起谈.NET技术,浅谈.Net中容易混淆的委托和接口

  本文适合对委托和接口概念非常了解的朋友,并且欢迎各位朋友与Snake一起探讨有关这方面的知识.本文不适合对委托和接口概念或用途了解一知半解(模糊)的朋友,这篇文章可能会对您产生误导,请千万别看.

  在文章正式开始之前我需要将MSDN上对委托和接口的内容放上来,作为文章之基.

  委托:

  委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。

  委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法.

  委托具有以下特点:

  委托类似于 C++函数指针,但它们是类型安全的。

  委托允许将方法作为参数进行传递。

  委托可用于定义回调方法。

  委托可以链接在一起;例如,可以对一个事件调用多个方法。

  方法不必与委托签名完全匹配。有关更多信息,请参见在委托中使用变体(C#和 Visual Basic)。

  C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数。有关 Lambda 表达式的更多信息,请参见Anonymous Functions (C# Programming Guide)。

  接口:

  接口描述的是可属于任何类或结构的一组相关功能。接口可由方法、属性、事件、索引器或这四种成员类型的任意组合构成。接口不能包含字段。接口成员一定是公共的。

  当类或结构继承接口时,意味着该类或结构为该接口定义的所有成员提供实现。接口本身不提供类或结构能够以继承基类功能的方式继承的任何功能。但是,如果基类实现接口,派生类将继承该实现。

  类和结构可以按照类继承基类或结构的类似方式继承接口,但有两个例外:

  类或结构可继承多个接口。

  类或结构继承接口时,仅继承方法名称和签名,因为接口本身不包含实现。

  接口具有下列属性:

  接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。

  不能直接实例化接口。

  接口可以包含事件、索引器、方法和属性。

  接口不包含方法的实现。

  类和结构可从多个接口继承。

  接口自身可从多个接口继承。

  正文开始

  在写这些文字的时候我又将以上的各个概念熟悉了一遍,以防自己把自己忽悠混淆了.所以不适合群众请尽快退散.另外如果您看完上面的定义和特征后就从两者的混淆中走了出来,您也可以尝试继续往下看.

  首先,关于委托的用法,我们可以这样使用:

public int Calculate(Func del){ int a = 1, b = 2; return del(a, b); }

  我们可以通过传不同的Func来改变整个方法的结果.

public int Add(int a, int b)
{ return a + b; }
public int Sub(int a, int b)
{ return a - b; }
//调用方法如下
public void TestMethod()
{ int result = Calculate(Add);
//the result is 3 int anotherResult = Calculate(Sub);//the result is -1 }

  首先我在Calculate方法中已经确定了2个数的值,并且包括在该方法当中.在输出结果的时候能明显看出传递的委托不同,其结果也不同.我们使用委托来改变方法的执行内容,我们不但可以改变其方法的内容,也可以在执行该方法的时候顺便做点什么(比如说做个日志记录).

  噢,可能您觉得二者容易混淆的地方在于..我还是举个例子比较好解释.

public interface ICal { int Calculate(int a, int b); }//有多个类实现了ICal接口.
public class Add : ICal { public int Calculate(int a, int b){ return a + b; }}
public class Sub : ICal { public int Calculate(int a, int b)
{ return a - b; }}//然后通过调用不同类来获取不同的方法
public static void Main(){ ICal cal = new Add();
//ICal=new Sub(); Console.Write(cal.Calculate(1, 2)); }

  讲解一下,通过上面的例子我们可以知道在创建一个具有计算功能(Calculate)的接口ICal之后,产生了两个具有计算功能的具体类,分别是Add和Sub.为了要获得结果,我们创建了一个需要有计算功能的”坑”,并赋予能与此”坑”相匹配的类Add(或Sub),最后从该坑中调用Calculate的结果就行.

  貌似说的过去?好,那么我至少要让你觉得有个适用范围吧!看下面的例子.

  比如有个Person类的数组arr.这时候我们可以通过委托的方法实现arr的排序.可是系统怎么知道2个Person哪个排在前面,哪个该排在后面?这时候我们就可以传进一个委托来告诉系统Peron类的大小.

arr.Sort(p => { p.ID });

  该lambda表达式意思是丢给该Sort方法一个排序的Key(此key能够进行大小比较),那么Sort就可以根据此key来进行比较.那通过接口呢?首先得创建一个继承自IComparer的类,我就拿本身继承它吧.

  好吧,它本来是很麻烦的:

private int SortDelegate(Person p){ return p.ID; }
public void TestMethod(){ arr.Sort(new Func(SortDelegate)); }

  但是我们要承认C# 3.0带给我们的便利.

  现在,我们要让Person类实现接口的规定.

public int Compare(Person x, Person y){//假设person的ID是int类型 return x.ID -y.ID; }

  那么我们的实现方法就可能是这样:

arr.Sort((new Person() as IComparer) comp);

  首先我们看第一个委托例子:在Calculate时我们的委托被允许使用了该方法内的两个变量a,b从而改变了整个方法的结果.在整个过程中委托时很被动的,因为它不知道自己会在什么时候被触发.上面的例子很简单,使您没有这种感觉,而且前面说过在方法执行的时候当委托被触发我们可以干点别的,比如说做个日志记录什么的,此时接口有能力又不破坏方法本身运行结构,又能做日志记录吗?显然实现了接口的类只能重写一遍该方法.

  路人甲:那我在接口的实现中再调用一下原方法,最后在方法的前面或后面加入日志记录功能不就完了吗?

  Snake:杀鸡焉用宰牛刀?且不说再原方法的可行性,就算可行了,麻烦不说,万一这个方法执行有多个阶段,每个阶段都要日志记录呢?委托能深入方法,并且由方法控制它安放之地,让委托能起到关键作用,此时作为接口大哥的牛刀也剔不干净鸡骨上的肉哟~.

  其次说接口的优点.我们前面可以看到委托能深入方法,也就是说委托的关注群体是方法们,而接口关注的群体则是类们.接口让类必须实现相同签名的方法或属性,以便在程序中通过调用可变的方法.既然是因为类的关系,那么它的方法肯定是不可变的了,每个实现了该接口的类,即便功能差不多也要完完全全写一遍,但是类的地盘大,肚子里的墨水多,虽然在Add类中通过ICal可调用的方法也就一个Calculate(),但是在Calculate始终是Add类的子民,所以该Calculate方法可以调用Add类中所有能调用的资源.而如果是Sub类的话,它的子民Caculate可调用的资源又与Add类不尽相同,毕竟同是Calculate,国籍不同,文化和生活方式也不同嘛.

时间: 2024-07-29 03:16:20

一起谈.NET技术,浅谈.Net中容易混淆的委托和接口的相关文章

浅谈.Net中容易混淆的委托和接口

本文适合对委托和接口概念非常了解的朋友,并且欢迎各位朋友与Snake一起探讨有关这方面的知识.本文不适合对委托和接口概念或用途了解一知半解(模糊)的朋友,这篇文章可能会对您产生误导,请千万别看. 在文章正式开始之前我需要将MSDN上对委托和接口的内容放上来,作为文章之基. 委托: 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法. 委托用于将方法作为参数传递给其他方法.事件处理程序就是通过委托调用的方法.您可以创建一个自定义方

吴佰元:浅谈GPS技术在国土资源中的应用

[硅谷网9月26日讯]原文载于<科技与生活>杂志2012年第14期,文章称,社会在不断的前进与发展,当代信息化的时代里,对于各项技术的发展来讲,都是具有十分良好的前景与较大的发展空间.所以这些新技术的出现,为社会为人们的生活带来很多的便利.因此,在当代我们要充分利用这些新技术.新产品的力量推动我国各项事业不断前进的步伐. 关键词GPS技术:http://www.aliyun.com/zixun/aggregation/30834.html">国土资源:应用 国土资源是国民经济中

一起谈.NET技术,.Net语言中关于AOP 的实现详解

文章主要和大家讲解开发应用系统时在.Net语言中关于AOP 的实现.LogAspect完成的功能主要是将Advice与业务对象的方法建立映射,并将其添加到Advice集合中.由于我们在AOP实现中,利用了xml配置文件来配置PointCut,因此对于所有Aspect而言,这些操作都是相同的,只要定义了正确的配置文件,将其读入即可.对于Aspect的SyncProcessMessage(),由于拦截和织入的方法是一样的,不同的只是Advice的逻辑而已,因此在所有Aspect的公共基类中已经提供了

技术人员谈管理之浅谈团队管理

古语云":马,匹马徘徊,万马奔腾;人,单影单身难行,合群大成."团队是由一些拥有互补技能,为了共同目标而遵循共同方法和行为规则,相互承担责任的人组成的群体. 谈团队管理就不能不提人力资源管理,人力资源管理简单的理解就是管人,由于人才是企业最重要的财富,因此人力资源管理的重要性可想而知. 人力资源管理的过程包括如下4个方面: 1.      制定人力志愿计划 人力资源计划包括识别和记录项目角色.责任和汇报关系. 2.      组建项目团队 组建团队就是找人,为项目工作找到所需的人员以及

一起谈.NET技术,ASP.NET中如何正确使用Session

Asp.Net中的Session要比Asp中的Session灵活和强大很多,同时也复杂很多:看到有一些Asp.Net开发人员报怨说Session不稳定,莫名其妙的丢失,其实这正是Asp.Net改进的地方之一. 我们知道Session与Cookie最大的区别在于:Cookie信息全部存放于客户端,Session则只是将一个ID存放在客户端做为与服务端验证的标记,而真正的数据都是放在服务端的内存之中的. 在传统web编程语言(比如asp)中,session的过期完全是按照TimeOut来老老实实处理

一起谈.NET技术,从.NET中委托写法的演变谈开去(上):委托与匿名方法

在<关于最近面试的一点感想>一文中,Michael同学谈到他在面试时询问对方"delegate在.net framework1.1,2.0,3.5各可以怎么写"这个问题.于是乎,有朋友回复道"请问楼主,茴香豆的茴有几种写法","当代孔乙己",独乐,众乐.看了所有的评论,除了某些朋友认为"的确不该不知道这个问题"之外,似乎没有什么人在明确支持楼主. 不过我支持,为什么?因为我也提过出这样的问题. 这样,我们暂且不提应

一起谈.NET技术,从.NET中委托写法的演变谈开去(中):Lambda表达式及其优势

在上一篇文章中我们简单探讨了.NET 1.x和.NET 2.0中委托表现形式的变化,以及.NET 2.0中匿名方法的优势.目的及注意事项.那么现在我们来谈一下.NET 3.5(C# 3.0)中,委托的表现形式又演变成了什么样子,还有什么特点和作用. .NET 3.5中委托的写法(Lambda表达式) Lambda表达式在C#中的写法是"arg-list => expr-body","=>"符号左边为表达式的参数列表,右边则是表达式体(body).参数列表

偷也是门技术——浅谈XMLHTTP应用:新闻小偷[转]

xml 本文参考互联网整理而成(在此感谢资料奉献者).希望本文尽量系统,尽量易懂. 偷,即无劳而获.在网络上,诸如某大型权威站点发布了新闻,而自己的小小站点也想与时俱进,和人家一样同步更新,多N啊.于是,偷就是最好的办法了.偷是不道德的,不鼓励偷,但又不提倡不偷,都是技术惹的祸,扯远了~! 小偷程序是什么? 其实是通过XML中的XMLHTTP对象调用其它网站上的网页,甚至可以将接受的HTML代码进行过滤以获得需要内容(比如提取某某气象站,不可能是将整站提取显示,而只是需要显示天气的那部分). 其

民用报警服务技术浅谈

报警行业的设备和系统数字化.网络化的速度在加快,未来的报警服务行业市场是网络化的专属,传统的报警服务商业模式正在发生变化,通过卖产品和施工实现盈利的方式在弱化.在互联网时代,报警服务企业在实现技术变现的时候,更多要依靠服务去获得市场和用户的认可. 相对于传统的报警设备,网络化的报警设备在布线和安装上都有了长足的进步,加上IPC的软硬件,以及移动端的开发应用,如今的报警操作系统不仅使用方便,提高用户的使用体验,还改变了传统报警的样式,使得接警人员对报警区域进行可视化联动操作,降低误报率和报警运营中