Delegate来谈C#

合集下载

c#委托(delegate)揭秘

c#委托(delegate)揭秘

c#委托(delegate)揭秘委托是⼀种定义⽅法签名的类型。

当实例化委托时,您可以将其实例与任何具有兼容签名的⽅法相关联。

您可以通过委托实例调⽤⽅法。

在表⾯上,委托很简单,使⽤new来构造委托实例。

使⽤委托实例的变量名来调⽤回调函数。

实际情况是编译器,CLR在幕后做了⼤量的⼯作来隐藏其复杂性,只有了解了这些幕后的东西,你才能真正的掌握它、灵活的运⽤它。

1、声明委托namespace DelegateDemo{internal delegate void HelloCallBack(string name);class Program{static void Main(string[] args){}}}通过ildasm查看中间代码,如下编译器⾃动⽣成⼀个helloCallBack的类,类⾥⾯有构造⽅法,回调⽅法Invoke,异步回调⽅法(BeginInvoke,EndInvoke),它继承MulticastDelegate类,MulticastDelegate继承Delegate类,c#有两个委托类(Delegate,MulticastDelegate)是有历史原因的,原来是要合并成⼀个类,但快到发布时间了,合并它需要重新测试,所以Delegate就幸存下来)。

2、委托的实例化internal delegate void HelloCallBack(string name);class Program{static void Main(string[] args){HelloCallBack helloShow = new HelloCallBack(ShowName);Console.ReadLine();}static void ShowName(string name){Console.WriteLine(name);}}中间代码如下.method private hidebysig static void Main(string[] args) cil managed{.entrypoint / //第⼀个被执⾏的⽅法被称为⼊⼝函数// Code size 15 (0xf).maxstack 3 //定义函数代码所⽤堆栈的最⼤深度.locals init ([0] class DelegateDemo.HelloCallBack helloShow) //分配⼀个局部变量helloShowIL_0000: nop //如果修补操作码,则填充空间,未执⾏任何有意义的操作IL_0001: ldnull //将空引⽤推送到计算堆栈上IL_0002: ldftn void DelegateDemo.Program::ShowName(string) //将ShowName的函数指针(⾮托管指针 native int 类型)推送到计算堆栈上IL_0008: newobj instance void DelegateDemo.HelloCallBack::.ctor(object, native int) //创建⼀个新对象,并将对象引⽤推送到计算堆栈上IL_000d: stloc.0 //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量helloShow中IL_000e: ret //从当前⽅法返回,并将返回值(如果存在)从调⽤⽅的计算堆栈推送到被调⽤⽅的计算堆栈上} // end of method Program::Main 从中间代码我们可以看到,HelloCallBack类构造函数有两个参数,HelloCallBack::.ctor(object, native int),⽽我的代码是HelloCallBack helloShow = new HelloCallBack(ShowName);只有⼀个参数,应该编译不过。

Delegate来谈C#

Delegate来谈C#

Delegate来谈C#之南宫帮珍创作Delegate是Dotnet1.0的时候已经存在的特性了, 但由于在实际工作中一直没有机会使用Delegate这个特性, 所以一直没有对它作整理.这两天, 我再度翻阅了一些关于Delegate的资料, 并开始正式整理这个C#中著名的特性.本文将由浅入深的谈一下Delegate这个特性.一.Delegate是什么?Delegate中文翻译为“委托”.Msdn中对Delegate的解释如下:C#中的委托类似于C或C++中的函数指针.使用委托使法式员可以将方法引用封装在委托对象内.然后可以将该委托对象传递给可调用所引用方法的代码, 而不用在编译时知道将调用哪个方法.与C或C++中的函数指针分歧, 委托是面向对象、类型平安的, 而且是平安的.如果你是第一次接触Delegate这个概念, 你可能会对上面这段文字感觉不知所云, 不外没关系, 你可以先把Delegate认为就是一个函数指针.而当你面对一个虚无的概念时, 最好的应对方法就是直接看实例.下面一个简单的Delegate使用例子.class Program{static void OtherClassMethod(){Console.WriteLine("Delegate an other class's method");}static void Main(string[] args){var test = new TestDelegate();test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);test.delegateMethod += Program.OtherClassMethod;test.RunDelegateMethods();}}class TestDelegate{public delegate void DelegateMethod(); //声明了一个Delegate Typepublic DelegateMethod delegateMethod; //声明了一个Delegate对象public static void StaticMethod(){Console.WriteLine("Delegate a static method"); }public void NonStaticMethod(){Console.WriteLine("Delegate a non-static method");}public void RunDelegateMethods(){if(delegateMethod != null){Console.WriteLine("---------");delegateMethod.Invoke();Console.WriteLine("---------");}}}上面是一个Delegate的使用例子, 运行看看结果吧.下面我稍微解释一下:【1】public delegate void DelegateMethod();这里声明了一个Delegate的类型, 名为DelegateMethod, 这种Delegate类型可以搭载:返回值为void, 无传入参数的函数.【2】public DelegateMethod delegateMethod;这里声明了一个DelegateMethod的对象(即, 声明了某种Delegate类型的对象).区分:DelegateMethod是类型, delegateMethod是对象.【3】为什么上面说Delegate可以看做是函数指针呢?看下面这段代码:test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod); test.delegateMethod += Program.OtherClassMethod;这里delegateMethod搭载了3个函数, 而且可以通过调用delegateMethod.Invoke();运行被搭载的函数.这就是Delegate 可以看作为函数指针的原因.上面这段代码中, delegateMethod 只能搭载:返回值为void, 无传入参数的函数(见:NonStaticMethod, StaticMethod, OtherClassMethod的界说), 这和Delegate类型声明有关(见DelegateMethod的声明:public delegate void DelegateMethod()).【4】Delegate在搭载多个方法时, 可以通过+=增加搭载的函数, 也可以通过-=来去失落Delegate中的某个函数.二.Delegate和C++中函数指针的区别Delegate和C++中的函数指针很像, 但如果深入比较, 发现其实还是有区另外, 区别主要有三个方面(参考Stanley B. Lippman的一篇文章)1) 一个delegate对象一次可以搭载多个方法(methods), 而不是一次一个.当我们唤起一个搭载了多个方法(methods)的delegate, 所有方法以其“被搭载到delegate对象的顺序”被依次唤起.2) 一个delegate对象所搭载的方法(methods)其实不需要属于同一个类别.一个delegate对象所搭载的所有方法(methods)必需具有相同的原型和形式.然而, 这些方法(methods)可以即有static也有non-static, 可以由一个或多个分歧类另外成员组成.3) 一个delegate type的声明在实质上是创立了一个新的subtype instance, 该subtype 派生自.NET library framework 的abstract base classes Delegate 或MulticastDelegate, 它们提供一组public methods用以询访delegate对象或其搭载的方法(methods) , 与函数指针分歧, 委托是面向对象、类型平安而且平安的.看完上面关于Delegate的介绍, 相信年夜家对它也有所了解了, 下面我们将进行更深入地讨论!三.Delegate什么时候该用?看完上面的介绍, 你可以会有一些疑问, 为什么会有Delegate?实际中什么时候会用到?什么时候应该去用?在回答这些问题之前, 年夜家可以先看看下面这段代码:class Program{static void Main(string[] args){var car = new Car(15);new Alerter(car);car.Run(120);}}class Car{public delegate void Notify(int value);public event Notify notifier;private int petrol = 0;public int Petrol{get { return petrol; }set{petrol = value;if (petrol < 10) //当petrol的值小于10时, 动身警报{if (notifier != null){notifier.Invoke(Petrol);}}}}public Car(int petrol){Petrol = petrol;}public void Run(int speed){int distance = 0;while (Petrol > 0){Thread.Sleep(500);Petrol--;distance += speed;Console.WriteLine("Car is running... Distance is " + distance.ToString());}}}class Alerter{public Alerter(Car car){car.notifier += new Car.Notify(NotEnoughPetrol);}public void NotEnoughPetrol(int value){Console.ForegroundColor = ConsoleColor.Red;Console.WriteLine("You only have " + value.ToString() + " gallon petrol left!");Console.ResetColor();}}看完了上面的代码后, 你可能会问:为什么不在public int Petrol中直接调用Alerter.NotEnoughPetrol呢?因为Car 模块和Alerter模块自己是两个自力的子系统, 如果直接调用,耦合性就会增加, 这不是我们愿意看到的.其实以上的代码是设计模式中的观察者模式(观察者模式又称Source/Listener模式)的实现, 当汽车在运行中汽油量<10时, 警报器便会发出警报.在上面代码中, Delegate相当于一个寄存回调函数的函数指针, 使用Delegate, 我们可以非常方便地实现观察者模式.而其实, 在需要使用回调函数时, 我们都可以考虑使用Delegate.不知道你有没有发现在上面的代码中还有一个问题呢?public event Notify notifier;上面的代码中, 我们界说了一个Event, 而事实上:public Notify notifier;这样写, 也完全可以满足我们的需求, 这就引出了我们的另一个问题, Delegate和Event!【1】Delegate和Event的关系看微软的代码时, 我们会发现Delegate和Event这两个关键字经常会一起呈现!究竟他们是什么关系呢?在Msdn中, 有一段话描述Delegate和Event之间的关系, 其实很简单:声明事件:若要在类内声明事件, 首先必需声明该事件的委托类型.【2】Delegate和Event配合使用的效果看下面几幅图, 这是我从一个C#的Application法式截下来的:从上图看到, 在响应图形界面的把持中, 我们用到了Event和Delegate, 相信这也我们使用Event和Delegate最频繁的处所了.这里我还想罗嗦一下, 平时需要我们自己写代码的界面事件响应函数, 如:button_C lick(…), 其实都是回调函数, 在自动生成的文件Form1.Designer.cs中, VS把事件和其对应的回调函数(即:button_Click(…)等)关联起来, 当触发某事件时, 对应的回调函数便会执行.【3】“public Notify notifier”和“public event Notify notifier”的区别关于这个问题, 我们直接ildasm看看IL代码吧:>“public Notify notifier”的IL代码, 如图:“publicevent Notif y notifier”的IL代码, 如图:分歧其实已经很明显了, “public Notify notifier”相当于Class里面的Field, 访问级别是public, 而“publicevent Notify notifier”则相当于Property, 访问级别是private!由于以上的分歧, 他们在某些使用上, 会稍有分歧, 详细的可参考shensr写的《delegate vs. event》.创作时间:二零二一年六月三十日简单说一下, Invoke与BeginInvoke都是执行Delegate里的搭载函数, 而分歧的是:Invoke是一个同步方法, BeginInvoke是一个异步方法.关于这个, 有一篇文章《Invoke and BeginInvoke》, 对此介绍的比力详细, 这里就未几说了.回顾一下, 究竟什么时候我们可能会用到Delegate:【1】.当我们在C#中需要类似函数指针这样工具时.【2】.当我们需要使用回调函数的时候.【3】.需要异法式用的时候.【4】.实现观察者模式的时候.【5】.处置事件响应的时候.创作时间:二零二一年六月三十日。

深入理解C#之委托(delegate)

深入理解C#之委托(delegate)

深⼊理解C#之委托(delegate) C#委托类似C语⾔中的函数指针.⼀, C# 委托的4个条件:1.声明委托类型 delegate int IntProcess(int num);2.必须有⼀个⽅法包含了要执⾏的代码 (返回值和形参列表个数&类型必须和声明的Delegate 完全⼀致) static int PrintIntNum(int num) { System.Console.WriteLine("Gavin Study Delegate {0}", num); return 1; } 3.创建委托实例TestIntDelegate = new IntProcess(Program.PrintIntNum);4.调⽤委托实例TestIntDelegate.Invoke(1000);TestIntDelegate(90);⼆,合并删除委托1. 合并多个委托,可以采⽤bine,但是很少⽤,⼀般使⽤+或者+=操作符2.删除某个委托,可以采⽤Delegate.Remove,但是很少⽤,⼀般使⽤-或者-=操作符3.多个委托合并之后,会顺序执⾏,仅仅返回最后⼀个委托实例的返回值;如果某⼀委托实例异常,则后⾯的委托实例不执⾏三,SourceCodeusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;delegate int IntProcess(int num); // 声明委托类型namespace TestDelegate{ class Program { private int? Num; public Program(int? num = null) { Num = num; } static int PrintIntNum(int num) // 有⼀个⽅法包含了要执⾏的代码 { System.Console.WriteLine("Gavin Study Delegate {0}", num); return 1; } public int HelloIntNum(int num) // 有⼀个⽅法包含了要执⾏的代码 { System.Console.WriteLine("Gavin HelloIntNum Delegate {0}, {1}", num, Num); return 2; } static void Main(string[] args) { IntProcess TestIntDelegate, TestInt, CommonDelegate; TestIntDelegate = new IntProcess(Program.PrintIntNum); //创建委托实例 TestIntDelegate(5); //调⽤委托实例 TestIntDelegate(90); //调⽤委托实例 TestIntDelegate.Invoke(1000); //调⽤委托实例 Console.ReadKey(); Program instance = new Program(55); TestInt = new IntProcess(instance.HelloIntNum); // .创建委托实例 TestInt(88); //调⽤委托实例 int returnInt = TestInt.Invoke(9999); //调⽤委托实例 System.Console.WriteLine("Gavin Study returnInt {0}", returnInt); Console.ReadKey(); CommonDelegate = TestIntDelegate + TestInt; //委托合并 int returnNum = CommonDelegate(8888); ////委托合并返回值 System.Console.WriteLine("Gavin Study returnNum {0}", returnInt); Console.ReadKey(); CommonDelegate -= TestIntDelegate;// //委托移除 CommonDelegate(777); Console.ReadKey(); } }}运⾏结果:Gavin Study Delegate 5Gavin Study Delegate 90Gavin Study Delegate 1000Gavin HelloIntNum Delegate 88, 55Gavin HelloIntNum Delegate 9999, 55Gavin Study returnInt 2Gavin Study Delegate 8888Gavin HelloIntNum Delegate 8888, 55Gavin Study returnNum 2Gavin HelloIntNum Delegate 777, 55。

C#基础知识学习之?委托(delegate)与事件(event)之间的介绍

C#基础知识学习之?委托(delegate)与事件(event)之间的介绍

C#基础知识学习之✨委托(delegate)与事件(event)之间的介绍委托(delegate) 与事件(event)前言在之前的文章里介绍了C#中的委托(delegate)(Action、Func、Predicate)的基本含义及用法那本篇文章在这里还要介绍一个跟委托有很大关系的小伙伴——C#中的事件(event)事件跟委托是有很大联系的,所以也就导致很容易分不清他们两个,以及什么时候用这两个上面有博客提到委托,想单独了解委托的可以去看一下,本篇文章主要说一下什么是事件以及事件与委托的区别委托和事件的定义委托在这里再说一遍委托跟事件的简单定义(没有搜到特别准确的,都是大概定义,理解万岁)委托:delegate 是一种可用于封装命名或匿名方法的引用类型。

委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。

委托是一种动态调用方法的类型,属于引用型。

委托是对方法的抽象和封装。

委托对象实质上代表了方法的引用(即内存地址)委托允许将方法作为参数进行传递。

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

委托可以把多个方法链接在一起。

这样,在事件触发时可同时启动多个事件处理程序。

委托签名不需要与方法精确匹配。

事件事件:事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。

如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处理程序方法。

事件表示C#中已定义的一个对象,即处理通知过程的对象通常,每个事件的发生都会产生发送方和接收方。

在.net框架中,事件是将事件发送者(触发事件的对象)与事件接受者(处理事件的方法)相关联的一种代理类,即事件机制是通过代理类来实现的。

当一个事件被触发时,由该事件的代理来通知(调用)处理该事件的相应方法委托和事件的区别简单说了一下两者的定义,眼神好的小伙伴这时候就会发现,事件的说明里有提到一句话:“事件也可以算一种特殊的委托”,这句话不是特别准确,但是也不妨可以这样理解。

C#委托Delegate(一)基础介绍用法

C#委托Delegate(一)基础介绍用法

C#委托Delegate(一)基础介绍用法本文是根据书本&网络前人总结的。

1. 前言定义&介绍:委托Delegate是一个类,定义了方法的类型,使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大佬使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

我们知道委托是一个引用类型,所以它具有引用类型所具有的通性。

它保存的不是实际值,而是保存对存储在托管堆(managed heap)的对象的引用。

那它保存的是对什么的引用呢?它保存的是对函数(function)的引用。

首先要知道什么是委托,用最通俗易懂的话来讲,你就可以把委托看成是用来执行方法(函数)的一个东西。

委托类:当我们用delegate关键字声明委托时,编译器自动为我们生成类。

类的名字即为委托变量名,访问类型为定义的委托访问类型。

如public delegate void CallBack(string name, int number);定义的委托对应的类为CallBack,访问类型为public,该类继承自[mscorlib]System.MulticastDelegate。

如果我们定义委托的访问类型为private或者protected,则对应的委托类的访问类型为private 或者protected。

但是任何委托都继承自[mscorlib]System.MulticastDelegate。

2. 委托演变代码1)我们创建一个类LanguageSpeak,多国说的语言,包括中文、英文、法文。

与语言枚举,如下现在,我们在类LanguageSpeak添加个方法,用来让不同人选择不同的语言。

传入名字、语言。

最后我们,在调用语言,达到不同人说不同语言的目的。

2)现在我们来看看,如果增加一种语言,比如粤语,要在语言类LanguageSpeak中添加一个方法,也要在SpeakLanguage方法与枚举中添加相应的语言判断。

【C#】delegate和event-K#-博客园

【C#】delegate和event-K#-博客园

【C#】delegate和event-K#-博客园在C#中,所有的Type都是从Object派⽣⽽来,也就是说⼀切Type皆Object。

如果,再抽象⼀个层次,可以把函数也看成Object,可以⽤函数名+参数+返回值来标识这个函数对象。

把函数看成Object后,⾃然可以把函数作为成员、变量来⽤,甚⾄可以作为另⼀个函数的参数值、返回值!在C/C++中,⽤函数指针来实现这个功能。

在C#中,为了类型安全,回避了指针。

幸运的是,在C#中,有在语义上等价于函数指针的delegate类型。

⼀个delegate实例可以引⽤⼀个函数。

⼀旦把⼀个函数赋值给⼀个delegate,该delegate看起来就像是那个函数的替⾝。

由此可见,不同语⾔仅仅⽤不同的语法阐述了相同的思想!《重构》⼀书中,有"封装字段"这个重构,这是⼀个⾮常简单、⾮常朴素、⼀点都不花哨的重构。

但是,背后的思想⾮常深厚、深远、深邃。

在C#中有Property来实现这个重构。

没有它的话,我们可能要多写⼏⾏GetXXX()、SetXXX()了。

如果,那个Field不是普通的字段,恰恰是个函数字段(即delegate实例)咋办?难道函数字段就能暴露了吗?!既然,你已经接受了它,就要好好对待它,千万别虐待它!同样,在C#中有event来实现。

没有它的话,我们就⼜要多写⼏⾏AddXXX()、RemoveXXX()了!当你写下:public event EventHandler MyEvent;就相当于,写了:private EventHandler _myEvent;public event EventHandler MyEvent{ add { lock (this) { _myEvent += value; } } remove { lock (this) { _myEvent -= value; } }}是不是,与Property有异曲同⼯之效?!相信,⼤家对event存在性的疑虑已经消除!另外,很多⼈疑惑"为啥只有+=、-=,⽽没有="。

C#委托(delegate)、泛型委托和Lambda表达式

C#委托(delegate)、泛型委托和Lambda表达式⽬录# 什么是委托1、从数据结构来讲,委托是和类⼀样是⼀种⽤户⾃定义类型。

2、委托是⽅法的抽象,它存储的就是⼀系列具有相同参数和返回类型的⽅法的地址。

调⽤委托的时候,委托包含的所有⽅法将被执⾏。

# 委托声明、实例化和调⽤1、声明委托是⼀种特殊的类,因此委托的声明与类的声明⽅法类似,在任何可以声明类的地⽅都可以声明委托。

委托声明⽤delegate关键字,同时委托要指明⽅法参数和返回值,写法与⽅法类似。

综合类的声明和⽅法的声明,委托声明写成如下形式:[访问修饰符] delegate 返回值类型委托名(形参列表);public delegate void MyDel();//定义了⼀个委托MyDel,它可以注册返回void类型且没有参数的函数public delegate void MyDel1(string str);//定义了⼀个委托MyDel1,它可以注册返回void类型且有⼀个string作为参数的函数public delegate int MyDel2(int a,int b);//定义了⼀个委托MyDel2,它可以注册返回int类型且有两个int作为参数的函数2、委托的实例化与普通类的使⽤⽅法相同,声明了委托之后,我们必须给委托传递⼀个具体的⽅法,才能在运⾏时调⽤委托实例。

委托实例包含了被传递给它的⽅法的信息,在运⾏时,调⽤委托实例就相当于执⾏它当中的⽅法。

委托实例化格式如下:委托类名委托实例名 = new 委托类名(Target) ;其中,委托实例名是⾃定义的名称,Target是要传⼊的⽅法的名称。

注意,Target是⽅法的引⽤,不能带()。

带()的话是该⽅法的调⽤。

区分引⽤和调⽤。

委托的实例化还有⼀种简单的⽅法:委托类名委托实例名 = Target;在需要委托实例的地⽅直接传⼊Target引⽤即可,C#编译器会⾃动根据委托类型进⾏验证,这称为“委托推断”。

c#委托delegate

c#委托delegate委托是⼀种存储函数引⽤的类型,在事件和事件的处理时有重要的⽤途通俗的说,委托是⼀个可以引⽤⽅法的类型,当创建⼀个委托,也就创建⼀个引⽤⽅法的变量,进⽽就可以调⽤那个⽅法,即委托可以调⽤它所指的⽅法。

1. 使⽤委托委托的使⽤需要以下步骤:定义委托delegate double ParocessDelegate(double param1,double param2);委托的定义⾮常类似于函数,但不带函数体,且要使⽤delegate关键字。

委托定义需要指明委托名称以及⼀个返回类型和⼀个参数列表声明委托类型的变量ProcessDelegate process;定义了委托后,就可以声明⼀个该委托类型的变量初始化委托变量process =new ProcessDelegate(Multiply);初始化委托变量时要把⼀个函数(此处Multiply为⼀个函数的名称)引⽤赋给委托变量,此函数需要具有与委托相同的返回类型和参数列表。

c#使⽤上述略显古怪的语法,使⽤new关键字创建⼀个新的委托,参数为要引⽤所需的函数,这是委托赋值的⼀个独特语法,函数名称是不带括号的还可以⽤另⼀种略微简单的语法process = Muiltiply;有了引⽤函数的委托变量之后,我们就可以⽤委托变量调⽤Muiltiply函数;也可以把委托变量传递给其他函数process (param1,param2);⽰例:namespace Delegate{public delegate int Call(int num1, int num2);//第⼀步:定义委托类型class SimpleMath{// 乘法⽅法public int Multiply(int num1, int num2){return num1 * num2;}// 除法⽅法public int Divide(int num1, int num2){return num1 / num2;}}}class Test{static void Main(string[] args){Call objCall;//第⼆步:声明委托变量// Math 类的对象SimpleMath objMath = new SimpleMath();// 第三步:初始化委托变量,将⽅法与委托关联起来objCall = new Call(objMath.Multiply);objCall += objMath.Divide;//向委托增加⼀个⽅法//objCall -= objMath.Divide;//向委托减去⼀个⽅法// 调⽤委托实例,先执⾏objMath.Multiply,然后执⾏objMath.Divideint result = objCall(5, 3);System.Console.WriteLine("结果为 {0}", result);Console.ReadKey();}}注意事项:委托可以调⽤多个⽅法,即⼀个委托变量可以引⽤多个函数,称为多路⼴播可以使⽤+=和-=运算符实现⽅法的增加和减少⽆返回值的委托,引⽤了多少个⽅法就会执⾏多少个⽅法。

C#的委托Delegate

C#的委托Delegate⼀、委托基础 1.什么是委托 委托(Delegate)是存有对某个⽅法的引⽤的⼀种引⽤类型变量,⽤关键字delegate申明,实现相同返回值和参数的函数的动态调⽤,提供了对⽅法的抽象。

委托(Delegate)特别⽤于实现事件和回调⽅法。

所有的委托(Delegate)都派⽣⾃ System.Delegate 类。

2.声明委托 委托声明后决定了该委托可以引⽤的⽅法。

 public delegate string MyDelegate(int i); 上⾯声明的委托可以⽤于引⽤任何返回值为string类型并且参数为⼀个int类型的任意⽅法名的⽅法,例如下⾯这个: public static string GetStr(int i){return i.ToString();} 所以委托的声明格式为:访问修饰符+delegate+返回类型+类型名+参数。

3.初始化委托变量以及赋值 声明了委托类型后,和string、int等类型⼀样需要声明变量才能使⽤。

对于初始化变量的赋值有两种⽅式: (1)new实例化赋值 和⼀般的类实例化⼀样,在构造函数中传⼊⽅法名即可。

MyDelegate mydelegate = new MyDelegate(GetStr); (2)直接赋值 由于⽅法名称和相应的委托之间存在隐⾝转换,所以可以等于号赋值。

MyDelegate mydelegate = GetStr; 以上例⼦都是直接将⽅法名赋值给委托变量的,这是因为⽅法由static修饰。

对于⾮静态的变量还是需要实例化使⽤,如下: MyDelegate mydelegate = new People().GetStr; 由于委托是引⽤类型,⽤ '=' 重新赋值后会改变⽅法的引⽤地址,下述例⼦也继续使⽤静态⽅法。

4.多播委托 委托对象可以通过 ‘+’ 运算法进⾏组合,⼀个合并委托调⽤所组合的委托的所有指向⽅法引⽤地址,合并的委托必须是相同类型的。

Delegate

.NET委托2009-07-12 01:59 by Complete, 25 visits, 网摘, 收藏, 编辑一。

基础概念委托相当于函数指针,它指向程序中另一个以后会被调用的一个或多个方法。

委托包含以下三个重要的信息:∙所调用的方法的名称∙该方法的参数(可选)∙该方法的返回值(可选)当一个委托被创建并提供了上述信息后,它可以在运行的时候动态的调用它所指向的方法。

二。

实例代码分析。

2.1 使用C#定义委托:在C#中使用delegate关键字定义委托,如下:public delegate void DelegateDemo(string name);这个委托可以指向public void Test(string name){}; 这个方法的签名必须要匹配委托的签名,即:返回值:void。

参数类型:string。

参数个数:1个最简单的委托实例:1: class Program2: {3:4: //定义一个委托5: public delegate void DelegateDemo(string info);6:7:8: //上面的委托可以指向这个方法9: public static void Test(string info)10: {11: Console.WriteLine(info);12: }13:14: static void Main(string[] args)15: {16:17: //将委托指向你要调用的方法18: DelegateDemo dela = new DelegateDemo(Program.Test);19:20:21: //使用委托22: dela("委托");23:24:25: }26: }代码分析:其实c#编译器在处理上面的委托时,会先自动产生一个派生自System.MulticastDelegate的密封类,这个类和它的基类System.Delegate一起为委托提供必要的基础设施。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Delegate来谈C# Delegate是Dotnet1.0的时候已经存在的特性了,但由于在实际工作中一直没有机会使用Delegate这个特性,所以一直没有对它作整理。这两天,我再度翻阅了一些关于Delegate的资料,并开始正式整理这个C#中著名的特性。本文将由浅入深的谈一下Delegate这个特性。

一.Delegate是什么? Delegate中文翻译为“委托”。Msdn中对Delegate的解释如下: C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。

如果你是第一次接触Delegate这个概念,你可能会对上面这段文字感觉不知所云,不过不要紧,你可以先把Delegate认为就是一个函数指针。

而当你面对一个虚无的概念时,最好的应对方法就是直接看实例。下面一个简单的Delegate使用例子。

class Program { static void OtherClassMethod(){ Console.WriteLine("Delegate an other class's method"); }

static void Main(string[] args) { var test = new TestDelegate(); test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod); test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod); test.delegateMethod += Program.OtherClassMethod; test.RunDelegateMethods(); } }

class TestDelegate { public delegate void DelegateMethod(); //声明了一个Delegate Type

public DelegateMethod delegateMethod; //声明了一个Delegate对象 public static void StaticMethod() { Console.WriteLine("Delegate a static method"); }

public void NonStaticMethod() { Console.WriteLine("Delegate a non-static method"); }

public void RunDelegateMethods() { if(delegateMethod != null){ Console.WriteLine("---------"); delegateMethod.Invoke();Console.WriteLine("---------"); } } } 上面是一个Delegate的使用例子,运行看看结果吧。下面我稍微解释一下:

【1】public delegate void DelegateMethod();这里声明了一个Delegate的类型,名为DelegateMethod,这种Delegate类型可以搭载:返回值为void,无传入参数的函数。

【2】public DelegateMethod delegateMethod;这里声明了一个DelegateMethod的对象(即,声明了某种Delegate类型的对象)。

区分:DelegateMethod是类型,delegateMethod是对象。 【3】为什么上面说Delegate可以看做是函数指针呢?看下面这段代码: test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod); test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod); test.delegateMethod += Program.OtherClassMethod;这里delegateMethod搭载了3个函数,而且可以通过调用delegateMethod.Invoke();运行被搭载的函数。这就是Delegate可以看作为函数指针的原因。上面这段代码中,delegateMethod只能搭载:返回值为void,无传入参数的函数(见:NonStaticMethod,StaticMethod,OtherClassMethod的定义),这和Delegate类型声明有关(见DelegateMethod的声明:public delegate void DelegateMethod())。

【4】Delegate在搭载多个方法时,可以通过+=增加搭载的函数,也可以通过-=来去掉Delegate中的某个函数。

二.Delegate和C++中函数指针的区别 Delegate和C++中的函数指针很像,但如果深入对比,发现其实还是有区别的,区别主要有三个方面(参考Stanley B. Lippman的一篇文章) 1) 一个 delegate对象一次可以搭载多个方法(methods),而不是一次一个。当我们唤起一个搭载了多个方法(methods)的delegate,所有方法以其“被搭载到delegate对象的顺序”被依次唤起。

2) 一个delegate对象所搭载的方法(methods)并不需要属于同一个类别。一个delegate对象所搭载的所有方法(methods)必须具有相同的原型和形式。然而,这些方法(methods)可以即有static也有non-static,可以由一个或多个不同类别的成员组成。

3) 一个delegate type的声明在本质上是创建了一个新的subtype instance,该 subtype 派生自 .NET library framework 的 abstract base classes Delegate 或 MulticastDelegate,它们提供一组public methods用以询访delegate对象或其搭载的方法(methods) ,与函数指针不同,委托是面向对象、类型安全并且安全的。

看完上面关于Delegate的介绍,相信大家对它也有所了解了,下面我们将进行更深入地讨论!

三.Delegate什么时候该用? 看完上面的介绍,你可以会有一些疑问,为什么会有Delegate?实际中什么时候会用到?什么时候应该去用? 在回答这些问题之前,大家可以先看看下面这段代码:

class Program { static void Main(string[] args) { var car = new Car(15); new Alerter(car); car.Run(120); } }

class Car { public delegate void Notify(int value); public event Notify notifier;

private int petrol = 0; public int Petrol { get { return petrol; } set { petrol = value; if (petrol < 10) //当petrol的值小于10时,出发警报 { if (notifier != null) { notifier.Invoke(Petrol); } } } }

public Car(int petrol) { Petrol = petrol; }

public void Run(int speed) { int distance = 0; while (Petrol > 0) { Thread.Sleep(500); Petrol--; distance += speed; Console.WriteLine("Car is running... Distance is " + distance.ToString()); } } }

class Alerter { public Alerter(Car car) { car.notifier += new Car.Notify(NotEnoughPetrol); }

public void NotEnoughPetrol(int value) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("You only have " + value.ToString() + " gallon petrol left!"); Console.ResetColor(); } }看完了上面的代码后,你可能会问:为什么不在public int Petrol中直接调用Alerter.NotEnoughPetrol呢?因为Car模块和Alerter模块本身是两个独立的子系统,如果直

相关文档
最新文档