您好,欢迎访问三七文档
如果你有C++的编程背景,那这个问题就很简单了:C#中的delegate和C++中的函数指针基本是一回事,C#正是以delegate的形式实现了函数指针。不同的地方在于C#中delegate是类型安全的。如果没有C或者C++的背景知识也没有一点关系。要理解Delegate,首先,你要明白,它是一个类,他和Class是一个级别的概念,不同在于Class的定义包含字段和方法,而delegate只包含方法的细节。定义Delegate:publicdelegateboolCompareDelegate(inta,intb);上面语句的含义是:定义了一个委托的实例时,这些实例都要包含一个方法名,并且这个方法必须有两个int型的参数,并且必须返回一个bool型的值。好,现在就创建一个上面定义的委托的实例publicCompareDelegatemyCompare=newCompareDelegate(CompareMethod);里面的这个CompareMethod是一个方法:定义如下:publicstaticboolCompareMethod(intx,inty){boolresult=xy?true:false;returnresult;}怎么使用呢inta=10;intb=15;boolisBigger=myDelegate(a,b);下面是完整的代码:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingCommon;namespaceConsoleApplication8{//定义委托publicdelegateboolCompareDelegate(inta,intb);publicclassMyCompare{///summary///定义一个方法,符合上面定义的委托所要求的方法细节,返回值为bool型,两个参数分别为int型////summary///paramname=x/param///paramname=y/param///returns/returnspublicstaticboolCompareMethod(intx,inty){boolresult=xy?true:false;returnresult;}}classProgram{staticvoidMain(string[]args){//实例化委托并初始化。注意初始化时候,必须包含一个方法的名称,而且这个方法必须符合最初定义委托时候的签名(参数类型和返回值)CompareDelegatemyDelegate=newCompareDelegate(MyCompare.CompareMethod);//现在我们使用委托实例来比较两个数a和b的的大小inta=10;intb=15;boolisBigger=myDelegate(a,b);Console.WriteLine(ab?:+isBigger);Console.Read();}}}是不是太简单了。C#中委托用来干什么呢,当然不是用来实现象上面那样的弱智程序。在C#中一提委托,一般就会引出另外一个术语:事件。C#中事件的实现,正是依赖于delegate。而事件又是一个很重要的概念,只有真正理解了委托,才能打好基础,真正的弄明白事件。代理(Delegate)大多数情况下,当调用函数时我们会指定要直接调用的函数。比如类MyClass如具有一个名为Process的函数,我们通常会按如下方法进行调用:MyClassmyClass=newMyClass();myClass.Process();这种调用在大多数情况下都是可行的。但是有些时候,我们不想直接调用函数,而希望能够将它传递给其他人,让他们进行调用。在以事件驱动的系统(如图形用户界面)中,这种方法尤为有用。例如当我需要在用户单击某个按钮即可执行一些代码时,或者当我要记录一些信息但却无法指定记录方式时。考虑以下示例:publicclassMyClass{publicvoidProcess(){Console.WriteLine(Process()begin);//这里还有其他东西...Console.WriteLine(Process()end);}}在此类中,我们进行一些记录,以了解函数的开始时间和结束时间。但是,我们的记录仅限于发送到控制台,这可能不是我们所需要的。我们真正需要的是能够控制从函数外部记录信息的位置,同时不必使函数代码变得复杂。在这种情况下,代理便是理想的解决方法。代理使我们可以指定将要调用的函数,看起来好像不需要指定哪个函数一样。对代理的声明类似于对函数的声明,不同的是在这种情况下,我们所声明的是此代理可引用的函数签名。我们的例子将声明一个带有单个字符串参数且没有返回类型的代理。修改该类如下:publicclassMyClass{publicdelegatevoidLogHandler(stringmessage);publicvoidProcess(LogHandlerlogHandler){if(logHandler!=null)logHandler(Process()begin);//这里还有其他东西if(logHandler!=null)logHandler(Process()end);}}使用代理与直接调用函数相似。只是在调用函数前,我们需要检查代理是否为空(即不指向一个函数)。要调用Process()函数,我们需要声明一个与代理相匹配的记录函数,然后创建代理的实例,以指向该函数。然后,将此代理传递给Process()函数。classTest{staticvoidLogger(strings){Console.WriteLine(s);}publicstaticvoidMain(){MyClassmyClass=newMyClass();MyClass.LogHandlerlh=newMyClass.LogHandler(Logger);myClass.Process(lh);}}Logger()函数是一个我们要从Process()函数中调用的函数,我们对它进行了声明,使其与代理相匹配。在Main()中,我们创建代理的一个实例,然后将该函数传递给代理构造函数,使其指向该函数。最后,我们将代理传递给Process()函数,该函数接着调用Logger()函数。如果您习惯于使用C++语言,您可能会认为代理很像函数指针,这种想法非常接近于事实。但是,代理并不“仅仅”是函数指针,它还提供了其它多种功能。传递状态(PassingState)在上面的简单示例中,Logger()函数仅仅是输出些字符串。一个不同的函数可能把信息记录到文件中,但是要进行这种操作,该函数需要知道把信息写道什么文件中。对于Win32®而言,当您传递函数指针时,可随之传递状态。但是对于C#,这就没有必要了,因为代理既可指向静态函数,“也”可指向成员函数。以下是一个有关如何指向成员函数的示例:classFileLogger{FileStreamfileStream;StreamWriterstreamWriter;publicFileLogger(stringfilename){fileStream=newFileStream(filename,FileMode.Create);streamWriter=newStreamWriter(fileStream);}publicvoidLogger(strings){streamWriter.WriteLine(s);}publicvoidClose(){streamWriter.Close();fileStream.Close();}}classTest{publicstaticvoidMain(){FileLoggerfl=newFileLogger(process.log);MyClassmyClass=newMyClass();MyClass.LogHandlerlh=newMyClass.LogHandler(fl.Logger);myClass.Process(lh);fl.Close();}}FileLogger类仅封装文件。我们修改了Main()以使代理指向FileLogger的fl实例的Logger()函数。当从Process()中激活此代理时,将会调用成员函数并把字符串记录到相应的文件中。其优点在于,我们不必更改Process()函数-对代理来说代码都是相同的,无论引用的是静态函数还是成员函数,。
本文标题:c#代理
链接地址:https://www.777doc.com/doc-4690551 .html