《Effective C#》:用委托实现回调

2016-02-19 14:10 1 1 收藏

下面图老师小编要跟大家分享《Effective C#》:用委托实现回调,简单的过程中其实暗藏玄机,还是要细心学习,喜欢还请记得收藏哦!

【 tulaoshi.com - 编程语言 】

  委托属于C#中的新名词,它的应用也非常广泛,例如事件就是委托最简单而又直接的例子。

  那么首先说说什么是委托,其实委托在用过C或者C++的人看来就是函数指针,不过使用C#的大多数人都没有用过这两门语言,因此对委托的理解不是很深,对于委托可以简单的从字面去理解,即委托别人去执行某些操作,也就是说执行一个操作,而这个操作过程自身并不知道,只是委托过来让你去执行而已。

  参看如下这个例子。

 

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/) public delegate void HelloHandler( string Msg );

private void SayHello( string sMsg )
{
 MessageBox.Show( sMsg );
}

// delegate sample

HelloHandler hHello = new HelloHandler( SayHello );
hHello( "Hello World!" );


  例子很明显,在执行hHello的时候,并不知道具体的过程是什么样的,只是去执行而已。

  现在要说说委托能做些什么,那么先来分析一下事件,这也是委托用得最多的地方。一般事件的初始化需要绑定一个事件处理函数,那么当事件触发的时候,处理函数会被调用,也就是说在事件处理函数可以明确的知道,此事件是被触发了。例如,点击窗体的上的Button,它会把Click事件反馈给窗体。很明显,委托是处理对象之间的信息交互。除了事件外,委托的大多用处都和此类似,那么这样使用的好处在于降低对象之间耦合性。

  其次委托不同于以前函数指针的地方在于,可以绑定多个委托函数,例如:

 

public delegate void HelloHandler( string Msg );

private void WriteHello1( string sMsg )
{
 Debug.WriteLine( "WriteHello1:" + sMsg );
}

private void WriteHello2( string sMsg )
{
 Debug.WriteLine( "WriteHello2:" + sMsg );
}

// delegate sample

HelloHandler hHello = new HelloHandler( WriteHello1 );
hHello += new HelloHandler( WriteHello2 );
hHello( "Hello World!" );


  不过在这种情况下,由于绑定到委托上的函数是按照顺序执行的,所以有两个潜在的问题。

  第一个问题,当一个函数执行过程中产生异常,导致后面的不能进行执行。就上面的例子而言,如果在WriteHello1函数中出现异常,会导致WriteHello2不能被执行。

  另一个问题,就是委托执行的返回值,当绑定多个函数,委托执行的返回值是最后一个绑定函数执行后的返回值,那么通过这个值去做判断将会是不正确的。

  那么对于委托绑定多个函数,要注意的是不要把异常扩散出来,其次委托类型的返回值为void。

  如何去使用委托,很多人看了书上的例子,也知道委托的意义,但是无法把它和实际应用进行结合。那么在使用委托的时候,首先要明白几个问题,等各个问题清楚了,委托原型也就自然出来了。

  需要分析清楚的问题有如下几点。

  问题一,传递信息是什么,传递的时机是否固定,一次传递还是多次传递;

  问题二,用委托是否合适;

  问题三,哪一方是委托的调用端,而哪一方是委托的初始端;

  问题四,委托的初始化放在哪里比较合适。

  问题一是关键,这首先决定是否要使用委托来实现,其次如果要使用委托,那么需要确定委托函数类型。

  对于问题二来说,很多人可能就不解了。没错,委托是可以降低类型之间的耦合性,但是能起到这种作用的并不是只有委托这一种方法。很多情况下,用重载构造函数即可以达到这一目的,因此想问题的时候,不能局限于此。例如,很多人都做过弹出一个单独窗体对某一条记录进行修改,这里用委托可以实现,但是考虑到DataRow属于引用类型,而这个窗体脱离了数据记录就失去了意义,因此可以重载构造函数,在初始化窗体的时候,把记录传递给窗体就行了。相对而言,后者会更简单直接些。

  有了前两个问题的分析,不少人在写委托的时候,会把顺序写反了,因此程序执行的效果并不是设想中的那样,这一点要尤为注意。

  对于第四个问题来说,可以借鉴窗体的控件事件初始化部分代码,即委托的初始化采取就近原则,不过这不是唯一初始化的地方,这样写只是便于防止漏写。

  好了,对于委托大致说这么多,希望对大家有所帮助。

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

来源:https://www.tulaoshi.com/n/20160219/1606360.html

延伸阅读
WWW的工作基于客户机/服务器计算模型,由Web 浏览器(客户机)和Web服务器(服务器)构成,两者之间采用超文本传送协议(HTTP)进行通信,HTTP协议的作用原理包括四个步骤:连接,请求,应答。根据上述HTTP协议的作用原理,本文实现了GET请求的Web服务器程序的方法,通过创建TcpListener类对象,监听端口8080; 等待、接受客户机连接到端口8080...
using System; using System.IO; using System.Security.Cryptography; namespace Vavic { /// /// Security 的摘要说明。 /// public class Security { const string KEY_64 = "VavicApp"; const string IV_64 = "VavicApp"; //注意了,是8个字符,64位 public Security() { // // TODO: 在此处添加构造函数逻辑 // } publ...
本文向大家介绍Windows Sockets的一些关于用C#实现的原始套接字(Raw Socket)的编程,以及在此基础上实现的网络封包监视技术。同Winsock1相比,Winsock2最明显的就是支持了Raw Socket套接字类型,使用Raw Socket,可把网卡设置成混杂模式,在这种模式下,我们可以收到网络上的IP包,当然包括目的不是本机的IP包,通过原始套接字,我们也可以...
在C#中有两种类型的数据,一种是值类型数据,一种是引用类型数据。在编码的时候区分这两种类型数据,可以避免一些细小的编码错误。 首先说说什么类型是值类型,例如:int、float、bool之类的基础类型,以及用struct定义的类型,如:DateTime。除此外,如string,数组,以及用class定义的类型等都是引用类型。对于C#来说,很难罗列出...
一.概述: 本文通过一个实例向大家介绍用C# Builder进行Internet通讯编程的一些基本知识。我们知道.Net类包含了请求/响应层、应用协议层、传输层等层次。在本程序中,我们运用了位于请求/响应层的WebRequest类以及WebClient类等来实现高抽象程度的Internet通讯服务。本程序的功能是完成文件的下载。 二.实现原理: 程序实...

经验教程

592

收藏

65
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部