c#委托_c#委托重载 - CSDN
c#委托 订阅
C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。 [1] 展开全文
C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。 [1]
信息
类    别
程序设计语言
影响语言
C++、C#、D、Java、JavaScript、ObjectPHP等
创始时间
1972年
主要编译器
Visual C++、Clang、GCC、Turbo C等
中文名
C语言
创始人
Dennis MacAlistair Ritchie
发    源
BCPL语言
外文名
C Programming Language
c语言简介
C语言是一门面向过程的计算机编程语言,与C++、Java等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。C语言描述问题比汇编语言迅速、工作量小、可读性好、易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编语言代码生成的目标程序效率低10%~20%。因此,C语言可以编写系统软件。 [2]  当前阶段,在编程领域中,C语言的运用非常之多,它兼顾了高级语言和汇编语言的优点,相较于其它编程语言具有较大优势。计算机系统设计以及应用程序编写是C语言应用的两大领域。同时,C语言的普适较强,在许多计算机操作系统中都能够得到适用,且效率显著。 [3]  冯.诺依曼在1945年提出了现代计算机的若干思想,被后人称为冯.诺依曼思想,这是计算机发展史上的里程碑。自1945 年至今大多采用其结构,因此冯.诺依曼被称为计算机之父。他的体系结构计算机由运算器、控制器、存储器、输入设备、输出设备五大部件构成。 C语言拥有一套完整的理论体系经过了漫长的发展历史,在编程语言中具有举足轻重的地位。 [4] 
收起全文
精华内容
参与话题
  • C# 中的委托和事件(详解:简单易懂的讲解)

    万次阅读 多人点赞 2018-08-28 09:00:39
      本文转载自 ... C# 中的委托和事件(详解) https://www.cnblogs.com/newcapecjmc/p/7084026.html 基础:https://www.cnblogs.com/hongfei/p/3574239.html   中级...

     

     

    本文转载自 http://www.cnblogs.com/SkySoot/archive/2012/04/05/2433639.html

    C# 中的委托和事件(详解)

    https://www.cnblogs.com/newcapecjmc/p/7084026.html

    基础:https://www.cnblogs.com/hongfei/p/3574239.html

     

    中级:http://www.tracefact.net/tech/009.html

    https://blog.csdn.net/yijun494610095/article/details/62422746

     

    进阶:https://www.cnblogs.com/sjqq/p/6917497.html

     

    关于委托和事件分享三个博客内容:

    首先说明下:

    (1)C#中事件:事件时属于类的成员,所以要放在类的内部。

    (2)委托属于一个定义,是和类、接口类似的,通常放在外部。

    (因为大多数委托都要被重用)

    委托定义在类里面还是类外面视情况而定,一般定义在与类定义平级部分,

    且用public修饰,便于外部调用。

    若定义在类的内部,则必须通过调用该类的成员才能取得其委托的引用,

    频繁调用的情况下不合适。

    *委托定义在类内部,举例说明如下:

    Class A {
      //声明在这里是可以的~
      private delegate void test_del(int a);
      
      private void test(){...}

      public void start(){
        //声明在这里就不行了~
        private delegate void test_del(int a);
      }
    }

     

    委托是一种特殊的类,和普通类不同的是委托是对一类方法的抽象。

    因此只能在类内部定义内部类(包括委托、结构和枚举)而不能在方法中定义

     

     

    第一个:

    再谈C#委托与事件

     

    转自:http://ruizhinet.blog.163.com/blog/static/9921382820092801032681/

    之前写过一篇关于C#委托与事件的文章(见《C#委托和事件例析》),不过还是收到一些网友的提问。所以,今天再换另一个角度来详解一下这个问题。

    一、在控制台下使用委托和事件

    我们都知道,C#中有“接口”这个概念,所谓的“接口”就是定义一套标准,然后由实现类来具体实现其中的方法,所以说“接口,是一组类的抽象”。同样道理,我们可以将“委托”理解为“方法的抽象”,也就是说定义一个方法的模板,至于这个方法具体是怎么样的,就由方法自己去实现。

    我们知道接口的最大好处就是可以实现多态,同理,“委托”是可以实现方法的多态,当我们想调用某个具体方法的时候,我们不直接调用这个方法,而是去调用这个委托。当然,我们必须在具体方法和委托之间建立某种关联。

    下面我们来看例子。

    首先,我们定义一个委托:

    public delegate void SaySomething(string name);

    这跟抽象方法的语法格式很相似,只是多了一个关键字delegate。既然是对方法的一种抽象,那么我们最关注的当然就是方法的返回值以及方法的参数了。所以上面红色的部分就是我们定义出来的一个规矩,如果某个方法想委托我去做事,那么请你遵循我的规矩,就是返回值为void,参数为一个字符串。我们这个委托的含义是,当某个人来了,就向他说点东西。

    好,既然我们已经定义了这个规矩,下面我们就定义具体的方法了。

    public void SayHello(string name) {     Console.WriteLine("Hello," + name + "!"); }

    public void SayNiceToMeetYou(string name) {     Console.WriteLine("Nice to meet you," + name + "!"); }

    我们这里一共定义了两个方法,一个是向某人说Hello,另一个是向某人说Nice to meet you。我们看到,这里定义的两个方法的返回值和参数跟我们前面定义的“委托”是一致的。

    接下来,我们来看事件。

    public event SaySomething come;

    我们定义了一个事件,这个事件是“有人来了”,注意定义的时候我们使用event关键字,除此之外,我们还加上了前面定义的“委托”的名字。这个意思是说,我这个事件只会跟“SaySomething”打交道,并且,当我这个事件发生的时候,我会通知关注我的这些“委托”(再由这些“委托”去调用具体的方法)。

    我们来定义一个测试方法:

    public void test() {      SaySomething sayhello = new SaySomething(SayHello);     SaySomething saynice = new SaySomething(SayNiceToMeetYou);     come += sayhello;     come += saynice;     come("张三"); }

    方法体中的前面两行是用来实例化委托,注意我们用到了new关键字,就好像实例化一个类一样,然后传入一个参数,但这个参数不是string类型、也不是int类型,而是一个方法名。

    再下面两行就是将委托加到事件上,意思是说,如果你这个事件发生了,就告诉我一声。可以通过“+=”来将n个委托实例加到某个事件上,一旦这个事件发生,所有的这些委托实例都会得到通知。

    最后一行是触发一个事件,注意我们是直接用一个事件名,然后跟一个参数,这又跟“委托”中定义的那个规矩一致(即,要有一个string类型的参数)。

    最后运行一下

    static void Main(string[] args) {     Program program = new Program();     program.test();     Console.Read(); }

    我们回过头来再看一下“事件”的定义:

    public event SaySomething come;

    这里已经指出了“委托”的名字,所以,我们可以直接将方法加到事件上,而省略“委托”的实例化过程,因此上面的test()方法可以简单写为:

    public void test() {      come += SayHello;     come += SayNiceToMeetYou;     come("张三"); }

     

    二、在窗体中使用委托和事件

    上面的例子并不能体现委托和事件的优点,其实,委托和事件在C#中使用非常广泛,例如,当我们点击某个“按钮”的时候,就会有一个“Click”事件触发,而这个事件会通知“委托”,在C#窗体应用程序中,“委托”的名字比较规范,统一使用“EventHandler”,它的具体格式是“void EventHandler(object sender, EventArgs e);”。相信大家都写过下面这样子的HelloWorld程序:

    当点击按钮的时候弹出一个对话框。我们怎样实现的呢?你肯定会说,我们在设计窗口双击按钮,就会自动为我们生成类似如下的方法:

    private void button1_Click(object sender, EventArgs e) {     MessageBox.Show("我被点击了!!!"); }

    其实,这里用到的就是事件和委托,这里的button1_Click就是符合EventHandler委托规矩的一个具体的方法,即返回值为void,参数分别是一个object和EventArgs。

    我们可以在Form1.Designer.cs中看到如下代码:

    this.button1.Click += new System.EventHandler(this.button1_Click);

    可以看到,这里有一个Click事件,然后将一个委托实例附加到这个事件上,跟我们前面讲的控制台应用程序中的用法是完全一样的。那这个Click事件是怎么触发的呢?对于这些系统类的事件,并不用我们管。

    当然,我们也可以定义自己的事件和委托,例如我定义一个事件,这个事件就是输出对象的名字。

    我们这里定义了一个ShowName委托和一个btnclick事件。并且,在button1_Click()方法中触发这个btnclick事件。最后的结果是,当我们点击按钮的时候,首先弹出一个“我被点击了!!!”的对话框,然后确定之后再弹出另一个显示按钮名称的对话框:

     

    第二个 

    C#委托和事件例析  

    ah_bill是对Java了解相对较多,而对C#则是因工作需要才去看了一下,C#跟Java在语法上非常相似,而最初让我比较困惑的就是委托、事件部分,相信大多数初学者也有类似的困惑。经过跟Java的对比学习,发现这其实跟Java的监听、事件是等同的,只是表述上不同罢了。

    委托+事件是观察者模式的一个典型例子,所谓的委托其实就是观察者,它会关心某种事件,一旦这种事件被触发,这个观察者就会行动。

    下面是最近写的一个例子,相信能够加深大家对委托和事件的理解。

    using System; using System.Collections.Generic; using System.Text;

    namespace ConsoleApplication3

    {    

    public delegate void TimeEventHandler(object obj, TimeEventArgs  args); //定义一个委托,委托其实就是“方法模板”,就好像“类”是“对象”的模板一样。如果某个类想在事件触发的时候收到通知,它必须有一个符合这种格式的方法,在这个例子中,就是:返回类型为void,参数类型为object、TimeEventArgs。

    //TimeEventArgs是我们自己定义的一个类,用于保存事件中的参数。这里我们分别保存时间的时分秒。

        public class TimeEventArgs:EventArgs

           {        

                   private int hour;        

                   private int minute;

                   private int second;        

                   public TimeEventArgs(int hour, int minute, int second)       

                     {            

                             this.hour = hour;            

                             this.minute = minute;            

                             this.second = second;      

                   }        

                 public int Hour        

                 {            

                             get           

                            {                

                                 return hour;            

                          }        

               }        

              public int Minute        

                        {            

                              get            

                               {                

                                 return minute;            

                              }        

                       }        

             public int Second        

                      {            

                            get            

                            {                

                              return second;        

                           }        

                    }    

    }

     //这是一个观察者类,它有一个符合我们上面定义的“委托”的方法,也就是void ShowTime(object obj, TimeEventArgs args),从这个方法的定义可以看到,我们只会关心返回类型和方法的参数,而方法名称则无所谓。

       class MyTimeEventHandlerClass    

      {        

             public void ShowTime(object obj, TimeEventArgs args)        

             {            

                   Console.WriteLine("现在的时间是:"+args.Hour+":"+args.Minute+":"+args.Second);        

             }    

    }

    //时钟类     class Clock    

                 {

    //我们在这个类中定义了一个“TimeChanged”事件,注意其前面有两个关键字“event”和“TimeEventHandler”,其中event表示这是一个事件,而不是方法或属性;TimeEventHandler则指出,谁要监听TimeChanged事件,它就必须有一个符合TimeEventHandler(委托)的方法。        

                            public event TimeEventHandler TimeChanged;        

                            public Clock()        

                            {            

                                    TimeChanged = null; //注意,这里的null的含义是指TimeChanged事件当前还没有观察者关注它,如果某个观察者要关注TimeChanged事件,它必须要让这个事件知道,方法是使用操作符“+=”来借助委托将其加载到事件上。        

                            }

    //时钟开始走动,我们的目标是每秒钟触发一次TimeChanged事件        

                         public void go()        

                          {            

                                    DateTime initi = DateTime.Now;            

                                    int h1 = initi.Hour;            

                                    int m1 = initi.Minute;            

                                    int s1 = initi.Second;            

                                    while (true)            

                                     {                

                                          DateTime now = DateTime.Now;                

                                          int h2 = now.Hour;                

                                          int m2 = now.Minute;                

                                          int s2 = now.Second;                

                                            if (s2!=s1)                

                                              {                    

                                                   h1 = h2;                    

                                                   m1 = m2;                    

                                                    s1 = s2;

    //首先建立一个TimeEventArgs对象来保存相关参数,这里是时分秒。                    

    TimeEventArgs args = new TimeEventArgs(h2,m2, s2);

    //注意这种写法,这一句是用来触发事件,事件不是类,所以不用使用“new”关键字,而且我们看到,这里TimeChanged的两个参数跟我们的委托(TimeEventHandler)是一致的,其中第一个参数是触发这个事件的对象,我们这里使用的是一个时钟实例(this)。

                                                  TimeChanged(this, args);             

                                             }            

                                    }        

                           }    

               }

     

        class Program    

        {

            static void Main(string[] args)        

            {            

                     Clock clock = new Clock(); //实例化一个时钟            

                     MyTimeEventHandlerClass tehc = new MyTimeEventHandlerClass(); //实例化一个观察者类

    //将事件跟我们定义的观察者进行连接,这样,clock就会知道,每当TimeChanged事件被触发,就会去通知这个观察者,注意我们连接的时候使用的并不是直接的观察者类实例中的ShowTime()方法,而是一个委托,并在这个委托中传递ShowTime()方法,这也是“委托”的真正意义所在——我有一个方法,但我委托你来帮我关联到事件,因为事件只会直接跟委托打交道,而不是观察者的具体某个方法。            

                      clock.TimeChanged+=new TimeEventHandler(tehc.ShowTime);            

                      clock.go();        

           }    

        }

    }

    第三个博文:

    C#中的委托到底是什么概念??

    委托,简单理解是这样的.
    比如您要管您的孩子,把孩子送进了幼儿园.
    OK.此时您就把您的孩子委托给了幼儿园.
    当幼儿园放学,将孩子交还给您的手中.则是委托的回调.
    当然我这里的例子是说异步委托调用.您也可以同步.
    什么是同步委托调用?
    您去银行存钱.把钱给柜员.他们帮你点钞.存款然后给您存折或卡.
    那么您就相当于把钱委托给了柜员让他去执行存钱的这个函数.
    明白了么?

    Delegate
    delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与它的签名相匹配的方法的引用"。它所实现的功能与C/C++中的函数指针十分相似。它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m。但与函数指针相比,delegate有许多函数委托和事件在 .Net Framework中的应用非常广泛指针不具备的优点。首先,函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。

    实现一个delegate是很简单的,通过以下3个步骤即可实现一个delegate:
    1. 声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。
    2. 创建delegate对象,并"将你想要传递的函数作为参数传入"。
    3. 在要实现异步调用的地方,通过上一步创建的对象来调用方法。
    using System;

    public class MyDelegateTest
    {
    // 步骤1,声明delegate对象
    public delegate void MyDelegate(string name);

    // 这是我们欲传递的方法,它与MyDelegate具有相同的参数和返回值类型
    public static void MyDelegateFunc(string name)
    {
    Console.WriteLine("Hello, ", name);
    }
    public static void Main()
    {
    // 步骤2,创建delegate对象(实例??)
    MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);
    // 步骤3,调用delegate
    md("sam1111");
    }
    }
    输出结果是:Hello, sam1111

    了解了delegate,下面我们来看看,在C#中对事件是如何处理的。

    C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:
    public delegate void MyEventHandler(object sender, MyEventArgs e);
    其中的两个参数,sender代表事件发送者,e是事件参数类。MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从System.EventArgs类派生。当然,如果你的事件不含参数,那么可以直接用System.EventArgs类作为参数。

    就是这么简单,结合delegate的实现,我们可以将自定义事件的实现归结为以下几步:
    1.定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象。
    2.定义事件参数类,此类应当从System.EventArgs类派生。如果事件不带参数,这一步可以省略。
    3.定义"事件处理方法,它应当与delegate对象具有相同的参数和返回值类型"。
    4.用event关键字定义事件对象,它同时也是一个delegate对象。
    5.用+=操作符添加事件到事件队列中(-=操作符能够将事件从队列中删除)。
    6.在需要触发事件的地方用调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。名字是OnEventName。
    7. 在适当的地方调用事件触发方法触发事件。

    下面是一个简单的例子:

    using System;
    public class EventTest
    {
    // 步骤1,定义delegate对象
    public delegate void MyEventHandler(object sender, System.EventArgs e);
    // 步骤2(定义事件参数类)省略
    public class MyEventCls
    {
    // 步骤3,定义事件处理方法,它与delegate对象具有相同的参数和返回值类型
    public void MyEventFunc(object sender, System.EventArgs e)
    {
    Console.WriteLine("My event is ok!");
    }
    }
    // 步骤4,用event关键字定义事件对象
    private event MyEventHandler myevent;
    private MyEventCls myecls;
    public EventTest()
    {
    myecls = new MyEventCls();
    // 步骤5,用+=操作符将事件添加到队列中
    this.myevent += new MyEventHandler(myecls.MyEventFunc);
    }
    // 步骤6,以调用delegate的方式写事件触发函数
    protected void OnMyEvent(System.EventArgs e)
    {
    if(myevent != null)
    myevent(this, e);
    }
    public void RaiseEvent()
    {
    EventArgs e = new EventArgs();
    // 步骤7,触发事件
    OnMyEvent(e);
    }
    public static void Main()
    {
    EventTest et = new EventTest();
    Console.Write("Please input ''a'':");
    string s = Console.ReadLine();
    if(s == "a")
    {
    et.RaiseEvent();
    }
    else
    {
    Console.WriteLine("Error");
    }
    }
    }
    输出结果如下,红色为用户的输入:
    Please input ‘a’: a
    My event is ok!

    展开全文
  • c#委托(Delegates)--基本概念及使用

    万次阅读 多人点赞 2018-05-13 00:10:56
    在我这菜鸟理解上,委托就是可以用方法名调用另一方法的便捷方法,可以简化switch等语句的重复。最近做项目的时候恰好需要用到委托,便来复习及学习委托的使用。嗯...本人以前并没有用过,只是稍微知道而已。以下是...


       在我这菜鸟理解上,委托就是可以用方法名调用另一方法的便捷方法,可以简化switch等语句的重复。最近做项目的时候恰好需要用到委托,便来复习及学习委托的使用。嗯...本人以前并没有用过,只是稍微知道而已。以下是整理的笔记。

    一.委托的概念

        委托是用户自定义的类,它定义了方法的类型。储存的是一系列具有相同参数和返回类型方法的地址列表,调用委托时,此委托列表的所有方法都将被执行。

    二.委托类型的定义

    委托类型必须在被用来创建变量以及类型对象之前声明。

    委托类型的声明:

    1.以delegate关键字开头。

    2.返回类型+委托类型名+参数列表

    delegate void MyDel(int a)

    三.实例

    1)现在我们先创建了控制台程序,进行简单的实例

    namespace Func
    {
        public delegate void MyDel();//声明一个自定义委托
        class Program
        {
            static void Main(string[] args)
            {
                MyDel say1 = SayHi;
                MyDel say2 = new MyDel(SayHi);
                say1();
                say2();
            }
            static void SayHi()
            {
                Console.WriteLine("hi");
            }
        }
    }

    2)扩展实例

    namespace Func
    {
        public delegate int MyDel(int num);//声明一个自定义委托
        class Program
        {
            static int Add1(int a)
            {
                int b = 10 + a;
                Console.WriteLine("——Add1———");
                return b;
    
            }
    
            static int Add2(int a)
            {
                int b = 10 - a;
                Console.WriteLine("——Add2———");
                return b;
    
            }
    
            static void Calculate(MyDel ex, int a)
            {
                var result = ex(a);
                Console.WriteLine(result + "\n");
            }
    
            static void Main(string[] args)
            {
                Calculate(Add1, 1);
                Calculate(Add2, 10);
                Console.ReadKey();
            }
        }
    }

    结果如下图


    上面实现了把方法当作参数在另一个方法中传递或调用”;从上面可以看出,调用的方法和委托的返回类型,参数类型都必须一致。

    我们可以把委托作为参数传递给封装好了的方法,通过委托来动态的调用方法。


    四.委托的加减运算

    可以使用+=运算符,为委托新增方法。

    同样可以使用-=运算符,为委托移除方法。

    当委托列表中有几个方法时,调用委托时,则会依次经过各个方法,并返回列表最后一项方法的结果。

    namespace Func
    {
        public delegate int MyDel(int num);//声明一个自定义委托
        class Program
        {
    
            static int Add1(int a)
            {
                int b = 10 + a;
                Console.WriteLine("——Add1———");
                return b;
    
            }
    
            static int Add2(int a)
            {
                int b = 10 - a;
                Console.WriteLine("——Add2———");
                return b;
    
            }
    
            static void Calculate(MyDel ex, int a)
            {
                var result = ex(a);
                Console.WriteLine(result + "\n");
            }
    
            static void Main(string[] args)
            {
                //Calculate(Add1, 1);
                //Calculate(Add2, 10);
                MyDel myDel = Add1;
                myDel += Add2;
                Calculate(myDel, 10);
                Console.ReadKey();
            }
        }
    }

    结果如下图:



    那么有时候我们需要返回每个方法的结果,此方法就不适用了,那怎么才能实现每个方法的返回结果都可以获取到呢?后续再写了。今天就简单的介绍了委托的基本概念和使用。


    展开全文
  • C#中的委托关键字是 Delegate,委托类似于C/C++中函数的指针。是存有对某个方法引用的引用类型变量,可在运行时被改变。一般用于实现事件和回调方法。 注意:所有的委托都派生自 System.Delegate 类委托分为委托...

    640?wx_fmt=gif

    640?wx_fmt=jpeg

    作者 | 羽生结弦

    责编 | 胡雪蕊

    出品 | CSDN(CSDNnews)

    在C#中的委托关键字是 Delegate,委托类似于C/C++中函数的指针。是存有对某个方法引用的引用类型变量,可在运行时被改变。一般用于实现事件和回调方法。

    注意:所有的委托都派生自 System.Delegate 类委托分为 委托类型和委托实例,下面分别进行讲解。

     

    640?wx_fmt=png

    零、委托类型和委托实例

     

    1. 委托类型 

    委托类型定义了委托实例可以调用的方法、方法的返回类型和参数。我们可以通过委托类型的返回类型和参数来得知具体可以调用哪种方法。下面我们通过一个例子来看一下:

    (1)首先我们定义一个委托类型:

     

    
     

    csharp
    delegate string DemoDelegate(int num);

    (2)其次我们定义两个方法:

     

     

    
     

    csharp
    string IntToString(int num)
    {
        return num.ToString();
    }

    int StringToInt(string num)
    {
        return int.Parse(num);
    }

    我们来分析一下这两个代码段。首先我们定义了一个委托 DemoDelegate ,委托所定义的返回值类型是 string 类型,参数只包含一个,参数类型是 int。因此根据委托定义得知只有方法的返回值类型是 string 且参数只有一个,并且 参数类型是 int 时,委托才能调用。所以符合条件的方法就只有IntToString。

    2. 委托实例

    当把方法赋值给委托变量的时候就创建了委托实例。同样我们用一个例子来看一下:

     

     

    
     

    csharp
    static void Main(string[] args)
    {
        DemoDelegate dd = IntToString;
        string num = dd(123);
        // 将输出 string 类型 "123"
        Console.WriteLine(num);
    }

    委托实例本质上就是调用者委托委托方法调用被调用者,在这里就是 Main 方法委托DemoDelegate 去调用 IntToString 方法。这样做的好处是调用者和被调用者的耦合度降低了。

    小知识:上面的代码我们还可以这样写,这两种写法是等价的:

     

     

    
     

    csharp
    static void Main(string[] args)
    {
        DemoDelegate dd = new DemoDelegate(IntToString);
        string num = dd.Invoke(123);
        // 将输出 string 类型 "123"
        Console.WriteLine(num);
    }

    委托的用途很多,我们这里来看一个例子,这个例子展示了委托其中一种的用途

     

     

    
     

    csharp
    public delegate int DemoDelegate(int num);

    class Tool
    {
        public static void IntSquare(int[] intArray, DemoDelegate dd)
        {
            for (int i = 0; i < intArray.Length; i++)
            {
                intArray[i] = dd(intArray[i]);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            DemoDelegate dd = Square;
            int[] intArray = {2,4,6 };
            Tool.IntSquare(intArray, dd);
            for (int i = 0; i < intArray.Length; i++)
            {
                Console.WriteLine(intArray[i]);
            }

            Console.Read();
        }


        static int Square(int num)
        {
            return num * num;

        }
    }

    我们将委托提取出来,作为一个公共的,然后定义一个 Tool 类,其中定义了一个计算数组中每个值的方法,这个方法接受两个参数,一个是int类型的数组,另一个是 DemoDelegate 委托类型的参数。通过委托调用 Program 类中的 Square 方法来计算数组中每个数字的平方值。我们在 Main方法中将 Square 方法赋值给委托变量,然后见数组和委托变量一同传入刚才我们定义的 Tool 类中的 IntSquare 方法,最后输出值为:4、16、36。这种用途叫做编写插件式方法,插件式方法就是只有在运行时才将方法赋值给委托。

     

    640?wx_fmt=png

    多播委托

     

    前面的例子我们都是讲一个方法赋值给委托变量,这种叫单播委托。但是在大部分情况下我们需要将多个方法赋值给委托,这是我们就用到了多播委托。要把多个方法赋值给委托变量,我们需要用到 +和 += ,方法如下:

     

     

    
     

    csharp
    Delegate d = method1;
    d += method2;

    当我们调用委托 d 的时候,就会按照赋值顺序来调用方法,即先调用 method1 再调用 method2 。我们有时候也需要移除委托中的某个方法,这时我们可以用 - 和 -= 进行操作,比如我们移除前面例子中的 method1 方法:

     

     

    
     

    csharp
    d -= method1;

    当我们进行 + 或者 += 操作时,操作数可以是null,相当于把一个新值赋值给了委托变量,也就是说如下两种方法是等价的:

    方法一:

     

     

    
     

    csharp
    Delegate d = null;
    d += method1; 

    方法二:

     

     

    
     

    csharp
    d = method1;

    同理,当进行 - 或者 -= 操作时,相当于把null值赋给了委托变量。

    下面我们来看一下多播委托的例子:

     

     

    
     

    csharp
    public delegate int DemoDelegate(int num);
    static void Main(string[] args)
    {
        DemoDelegate dd = null;
        dd += Square;
        dd += Remainder;
        dd(5);
        Console.Read();
    }


    static int Square(int num)
    {
        Console.WriteLine(num * num);
        return num * num;
    }

    static int Remainder(int num)
    {
        Console.WriteLine(num % 2);
        return num % 2;
    }

    在代码中我们定义了两个方法,分别是计算数值平方的 Square 和计算数值除以2的余数Remainder 。在 Main 方法中我们利用 += 将两个方法赋值给委托变量 dd 。执行这段代码,最终输出结果为:25、1。当我们利用 - 或者 -= 来移除掉一个方法时,例如移除掉 Square ,这时就只会输出1,当我们把所有的方法都移除掉时,程序运行起来将会报空指针异常的错误。

     注意:
    1. 委托不可变,使用 **+=** 或者 **-=** 实际上是创建了新的委托实例,并把它付给当前的委托变量。
    2. 如果多播委托的返回类型不是void,那么调用者只能获取到最后一个被调用方法的返回值,前面方法的返回值将会被抛弃。
    3. c#会将 +、-、+=、-=编译为 Combine 和 Remove两个方法。

     

    640?wx_fmt=png

    实例方法委托和静态方法委托

     

    实例方法和静态方法都是c#中经常用到的方法,我们可以将这两种方法都赋值给委托,因此就出现了实例方法稳妥和静态方法委托。它们之间的区别如下:1. 一个实例方法被赋值给委托对象时,委托对象不仅要保留对方法的引用,还要保留方法所属实例的引用,这时 System.Delegate 中的Target 属性就表示的是方法所属的实例;

    2. 一个静态方法赋值给委托对象时,Target 属性值为null。例子如下:- 首先定义一个类 Demo 里边包含 NumAdd 实例方法和 Num 静态方法 

     

     

    
     

    csharp
    class Demo
    {
        public int NumAdd(int num)
        {
            return ++num;
        }

        public static int Num(int num)
        {
            return num;
        }

    接着在控制台中调用这两个方法

     

     

    
     

    csharp
    public delegate int DemoDelegate(int num);
    class Program
    {
        static void Main(string[] args)
        {
            Demo demo = new Demo();
            DemoDelegate dd = demo.NumAdd;
            dd(2);
            Console.WriteLine("方法所属实例:"+dd.Target);
            Console.WriteLine("调用方法:"+dd.Method);

            DemoDelegate staticDd = Demo.Num;
            staticDd(2);
            Console.WriteLine("方法所属实例:" + staticDd.Target);
            Console.WriteLine("调用方法:" + staticDd.Method);
            Console.ReadLine();
        }
    }

    运行以上代码,输出结果如下:

    640?wx_fmt=png

    我们可以看到,将静态方法赋值给委托对象后打印方法所属实例为空。

     

    640?wx_fmt=png

    泛型委托类型

     

    在一些情况下我们不确定参数类型和返回值类型,这时我们就需要用到泛型委托类型,语法如下:

     

     

    
     

    csharp
    public delegate T DemoDelegate<T>(T arg);

    我们具体看一下例子:

     

     

    
     

    csharp
    public delegate T DemoDelegate<T>(T num);

    class Demo
    {
        public int NumAdd(int num)
        {
            return ++num;
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            Demo demo = new Demo();
            DemoDelegate<int> dd = demo.NumAdd;
            Console.WriteLine(dd(2));
            Console.ReadLine();
        }
    }

    运行上面的代码,控制台将会输出结果 3

    注意:我们可以将返回值类型或者参数类型固定,例如:

     

     

    
     

    csharp
    public delegate string DemoDelegate<T>(T arg);
    public delegate T DemoDelegate<T>(int arg);

    使用泛型委托的好处是可以写出一组委托类型,这组方法可以拥有热议类型的返回值和任意数量的参数。下一小节我们就来看一下具体怎么用。

     

    640?wx_fmt=png

    Action 和 Func

     

    1. Func 

    Func是一个具有返回类型的方法,它的类型参数数量可以多达16个,其中包括0到多个输入类型参数和一个输出类型参数。下面的代码段展示了Func部分类型参数:

     

     

    
     

    csharp
    delegate void Action();
    delegate void Action<in T> (T t);
    delegate void Action(in T1,in T2)(T t1,T t2);

    2. Action 

    Action 是一个不具有返回类型的方法,他的类型参数数量同样多达16个。下面展示了部分Action类型参数:

     

     

    
     

    csharp
    delegate void Action();
    delegate void Action<in T> (T t);
    delegate void Action(in T1,in T2)(T t1,T t2);

    我们来看一下例子,以Func为例,Action同理

     

     

    
     

    csharp
    class Demo
    {
        public void Num<T>(T[] array, Func<T, T> func)
        {
            for (int i = 0; i < array.Length; i++)
            {
                Console.WriteLine(func(array[i]));
            }
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            Demo demo = new Demo();
            int[] array = new int[] {2,4,6 };
            demo.Num<int>(array, NumAdd);
            Console.ReadLine();
        }

        static int NumAdd(int num)
        {
            return ++num;
        }
    }

    从代码中可以看出,我们将 Demo 类中的 Num 方法的第二个参数类型写成了 Func<T,T>,这里的意思是委托实例的返回类型和类型参数都是T类型。我们在Main函数中通过委托,控制台输出结果是3、5、7 。这时我们就看出了使用 Func 和 Action 的优点了,我们不需要在外部显式的定义委托,比较方便。

     

    640?wx_fmt=png

    冷知识

     

    1. 委托与接口

    一般来说接口可以解决的问题,委托同样也可以解决,那么什么时候使用委托呢?我们来看一下:

    (1)当需要多播的时候;

    (2)订阅者需要多次实现接口的时候。

    2. 委托兼容性

    (1)委托类型

    委托类型之间互不兼容,即使它们的签名一样也不行,也就是说如下的写法是错误的。 

     

     

    
     

    csharp
    delegate void DD1();
    delegate void DD2();
    DD1 dd1=Method;
    DD2 dd2=dd1;

    (2)委托实例 

    如果委托实例具有相同的方法目标,那么委托实例就是相等的。

    (3)参数 

    当调用一个方法时,提供的参数可以比方法参数更具体。例如被调用的方法参数是 Object类型,但是提供的参数是 String 类型,这时程序不会报错,因为string 来自 object,string 比 object 更具体。(委托只支持引用转换)

    (4)返回值 

    同参数一样,当调用方法时,可以获得一个比被调用方法返回值更具体的返回值。

    作者简介:朱钢,笔名羽生结弦,CSDN博客专家,.NET高级开发工程师,7年一线开发经验,参与过电子政务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于北京恒创融慧科技发展有限公司,从事企业级安全监控系统的开发。

     

    【End】

    2019年Python全栈工程师薪资一路攀高,都是开发人员改怎么转向高收入?

    https://edu.csdn.net/topic/python115?utm_source=csdn_bw

    5G进入元年,物联网发展愈加火爆!

    你是否身怀绝技、却无人知晓;别让你的IoT项目再默默无闻了!

    继第一届AI优秀案例评选活动之后,2019年案例评选活动再度升级,CSDN将评选出TOP 30优秀IoT案例,赶快扫码参与评选吧!重磅福利,等你来领!

    640?wx_fmt=jpeg

    热 文 推 荐 

    ☞雷军:小米推动山寨机灭亡;苹果回应禁止第三方换电池;Javascript 引擎 V8 7.7 发布 | 极客头条

    从ACM班、百度到亚马逊,深度学习大牛李沐的开挂人生

    Chrome 为何会成功?

    《乐队的夏天》很酷?程序员式的摇滚才燃爆了!

    Kubernetes要成为一个企业友好平台,到底还缺啥?

    糟了,上网记录被 Python 扒下来了!

    AI芯片技术“分叉”百害无利,国产芯片大有可为

    ☞比特币勒索出新招,佳能单反被黑客攻破,白帽却利用一个漏洞赎回了照片,这波操作简直了……

    行!这下 CSDN 玩大了!粉丝:太良心

    640?wx_fmt=gif点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

     

     

     

     

     

    640?wx_fmt=png

    你点的每个“在看”,我都认真当成了喜欢

    展开全文
  • CSharp中的委托

    千次阅读 2016-11-11 16:33:43
    一、什么是委托 委托是一个类,它定义了方法的类型,使得可以将方法当作另外一个方法的参数来进行传递;调用委托的时候,委托包含的所有方法将被执行。 二、委托的定义 public delegate void MyDel(int x); ...

    一、什么是委托

    委托是一个类,它定义了方法的类型,使得可以将方法当作另外一个方法的参数来进行传递;调用委托的时候,委托包含的所有方法将被执行。

    二、委托的定义

    public delegate void MyDel(int x);

    public delegate string MyDel2(string msg);

    三、声明委托变量

    MyDel md;

    四、初始化委托

    md = new MyDel(方法名(intx));

    五、委托赋值

    md = 方法名(int x);

    六、多播委托

    MyDelmd = new MyDel(M1);

    md += M1; // 增加方法

    md += M1; // 增加方法

    md 1= M1;  // 减少方法

    七、委托的调用

    if(md !=null)

    md.Invoke();

    八、匿名方法

    delegate int MyDel (int x); //定义一个委托

    MyDeldel = delegate( int x){ return x; };

    九、Lambda表达式

    delegate int MyDel (int x); //定义一个委托

    MyDeldel2 = (int x) => {return x;};//Lambda表达式
    MyDel del3 = x => {return x};//简写的Lambda表达式

    十、委托示例

    1.委托实现不通的国家输出不同的问候语

            /// <summary>

            /// 定义无返回值带字符串参数的委托

            /// </summary>

            /// <paramname="name"></param>

            delegate void ShowHiDelegate(stringname);

     

            /// <summary>

            /// 输出问候语

            /// </summary>

            /// <paramname="name"></param>

            /// <paramname="show"></param>

            static void SayHi(string name,ShowHiDelegate show)

            {

                show.Invoke(name);

            }

     

            /// <summary>

            /// 输出中文问候语

            /// </summary>

           /// <param name="name">名字</param>

            static void SayChina(string name)

            {

                Console.WriteLine("你好:" + name);

            }

     

            /// <summary>

            /// 输出英文问候语

            /// </summary>

           /// <param name="name">名字</param>

            static void SayEnglish(string name)

            {

                Console.WriteLine("Hi," +name);

            }

     

            static void Main(string[] args)

            {

                ShowHiDelegate showChina = newShowHiDelegate(SayChina);

               // 输出中文问候语

                SayHi("张三", showChina);

     

                ShowHiDelegate showEnglish = newShowHiDelegate(SayEnglish);

               // 输出中文问候语

                SayHi("Tony",showEnglish);

     

               Console.WriteLine("----------------------------------------");

                Console.WriteLine("多播委托实现打招呼");

               //多播委托输出

                ShowHiDelegate sd = newShowHiDelegate(SayChina);

                sd += SayEnglish;

                SayHi("Tom", sd);

                Console.ReadKey();

            }

    输出结果:

    计算机生成了可选文字:, ile:/, 以 7 我 的 文 / v u 引 靈 u 引 。 2013/Projects/DelegateDemo/ConsoleDelegeteDemo/bin/„ 你 好 张 三 Hi-Tony 尔 好 灬 Hi.Tom

    十一、Lamdba表达式在实际中的应用

                List<int> list = newList<int>() { 1, 3, 2, 4, 6, 5, 8, 7, 9 };

                list.Sort();

                Console.WriteLine("操作源数组");

                foreach (int item in list)

                {

                    Console.Write(item +"\0");

                }

                Console.WriteLine();

     

                Console.WriteLine("找出大于4的所有数");

                // 找出大于4的数

                System.Collections.IEnumerableenumerable = list.Where(x => x > 4);

                foreach (int item in enumerable)

                {

                   Console.Write(item+"\0");

                }

                Console.WriteLine();

                Console.ReadKey();

    输出结果:

    计算机生成了可选文字:' ' 1 / 我 的 文 / vi “ e 丨 u 引 。 2013/Projects/DelegateDemo/ConsoleDetegateDemo/bin/... ' 一 操 作 源 数 组 1 2 3 4 5 6 7 8 9 找 出 大 于 4 的 所 有 数 5 6 7 8 9

    十二、C#中已定义好的委托(泛型委托Action<>)

    1.带参无返回值委托

    ///<summary>

    /// 输出问候语

    ///</summary>

    ///<param name="name"></param>

    ///<param name="show"></param>

    staticvoid SayHi(string name, Action<string> show)

    {

        show.Invoke(name);

    }

     

    ///<summary>

    /// 输出中文问候语

    ///</summary>

    /// <param name="name">名字</param>

    staticvoid SayChina(string name)

    {

       Console.WriteLine("你好:" +name);

    }

     

    ///<summary>

    /// 输出英文问候语

    ///</summary>

    /// <param name="name">名字</param>

    staticvoid SayEnglish(string name)

    {

        Console.WriteLine("Hi," + name);

    }

     

    staticvoid Main(string[] args)

    {

       #region 委托demo

        Action<string> showChina = newAction<string>(SayChina);

        // 输出中文问候语

       SayHi("张三", showChina);

     

        Action<string> showEnglish = newAction<string>(SayEnglish);

        // 输出中文问候语

        SayHi("Tony", showEnglish);

     

       Console.WriteLine("----------------------------------------");

       Console.WriteLine("多播委托实现打招呼");

        //多播委托输出

        Action<string> sd = newAction<string>(SayChina);

        sd += SayEnglish;

        SayHi("Tom", sd);

        Console.ReadKey();

        #endregion

    }

    2.带参带返回值委托(Func<>)

    ///<summary>

    /// 输出问候语

    ///</summary>

    ///<param name="name"></param>

    ///<param name="show"></param>

    publicstring SayHi(string name, Func<string, string> show)

    {

        return show.Invoke(name);

    }

     

    ///<summary>

    /// 输出中文问候语

    ///</summary>

    /// <param name="name">名字</param>

    publicstring SayChina(string name)

    {

       return "你好:" + name;

    }

     

    ///<summary>

    /// 输出英文问候语

    ///</summary>

    /// <param name="name">名字</param>

    publicstring SayEnglish(string name)

    {

        return "Hi," + name;

    }

    staticvoid Main(string[] args)

    {

     

     

       #region 委托demo(Func实例)

     

        FuncDemo fd = new FuncDemo();

        Func<string, string> showChina = newFunc<string, string>(fd.SayChina);

        // 输出中文问候语

       Console.WriteLine(fd.SayHi("张三",showChina));

     

        Func<string, string> showEnglish =new Func<string, string>(fd.SayEnglish);

        // 输出中文问候语

       Console.WriteLine(fd.SayHi("Tony", showEnglish));

     

       Console.WriteLine("----------------------------------------");

       Console.WriteLine("多播委托实现打招呼");

        //多播委托输出

        Func<string, string> sd = newFunc<string, string>(fd.SayChina);

        sd += fd.SayEnglish;

        foreach (Func<string, string> item insd.GetInvocationList())

        {

           Console.WriteLine(item.Invoke("Tom"));

        }

        Console.ReadKey();

        #endregion

    }

    输出结果:

    计算机生成了可选文字:, ile:/, 以 7 我 的 文 / v u 引 u 引 。 2013/Projects/DelegateDemo/ConsoleDetegateDemo/bin/... 你 好 张 三 Hi-Tony 尔 好 灬 Hi.Tom

    展开全文
  • Csharp委托详解

    千次阅读 2018-05-24 23:41:34
    using System; using System.Collections.Generic;...namespace Csharp委托和事件详解 { /* * 作者:Ai * 时间:2018.3.1 * * ps:委托和事件我已经学习了好几遍了,但隔得时间长了总是又忘记, ...
  • C#委托

    千次阅读 热门讨论 2014-12-14 16:32:03
    刚开始在C#视频中就看到了委托,到了大话中首先还是看这些基础知识,对于委托我始终不太理解,因此我就上网查了一些资料并且结合自己的理解,来介绍一下委托。  【汉语】  把事情托付给别人或别的机构。  ...
  • C# 委托

    2017-10-26 09:46:39
    C# 委托实际上类似于C++中的函数指针,因为C#中不存在指针,所以用委托可以完成一些原来在C++中用函数指针完成的操作,例如传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m。但与函数指针相比,...
  • C#委托使用

    千次阅读 2019-05-23 14:42:26
    C#委托使用案例 委托的使用 假定有两个对象A和B,在A中实例化了对象B,那么A可以访问B中的方法,反过来B不能直接访问A中的方法,所以使用委托。 委托的使用步骤:条件(在A对象中实例化了B) (1)、在B中声明一...
  • C# 委托 (一)—— 委托、 泛型委托与Lambda表达式

    万次阅读 多人点赞 2018-08-19 20:46:47
    1 委托的含义 2 委托声明、实例化和调用 2.1 委托的声明 2.2 委托的实例化 2.3 委托实例的调用 3 泛型委托 3.1 Func委托 3.2 Action委托 3.3 Predicate委托 4 匿名委托 5 Lambda表达式 5.1 表达式Lambda ...
  • [unity3d]unity中C#委托的应用

    万次阅读 多人点赞 2014-01-18 01:42:36
    C#中有一种还是挺实用的类型,就是...下面我就从参考网上的一个例子,讲解一下unity中C#委托的应用。 我们新建一个脚本,取名TestDelegate。这个主要的功能就是点击中文按钮输出中文名字,点击英文按钮输出英文名字。
  • C#委托和事件的概念

    千次阅读 2018-10-10 14:26:41
    一、事件的本质 事件是软件系统里的两个子系统之间,或者两个模块之间,或者两个对象之间发送消息,并处理消息的过程。在面向对象的世界里,就可以统一认为是两个对象之间的行为。 两个对象之间发送的这种消息,对...
  • 委托(delegate)是一种存储函数引用的类型。这听起来相当深奥,但其机制是非常简单的。委托的声明非常类似于函数,但不带函数体,且要使用delegate 关键字。委托的声明制定了一个返回类型和一个参数列表。 定义了...
  • C# 委托及各种写法

    千次阅读 2015-09-15 15:18:53
    委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)。 1、定义委托类型 [访问修饰符]delegate 返回类型 委托名(形参); 2、声明委托对象 委托委托实例名; 3、创建...
  • 最近遇到了一些C#委托相关的问题,貌似理解了,去写的时候又不知为何,所以就去查了些相关文章去了解,下面写下我的理解 首先什么是委托?菜鸟教程上是这样说的:C# 中的委托(Delegate)类似于 C 或 C++ 中函数的...
  • 深入理解C#委托及原理

    千次阅读 2011-10-25 17:22:04
    一、委托 设想,如果我们写了一个厨师做菜方法用来做菜,里面有 拿菜、切菜、配菜、炒菜 四个环节,但编写此方法代码的人想让 配菜 这个环节让调用方法的人实现,换句话说,就是想在方法被调用时接收 代码 作为...
  • C# 委托使用场景

    千次阅读 2018-09-26 12:26:38
    A1窗口打开B窗口,B窗口向A1窗口传值时使用到委托。只有A1打开B窗口时,可以直接在B调用A1中的(public)方法,这看不出委托的作用(前提是知道B窗口是A1窗口打开的)。 当有窗口A2也打开B窗口,同时需要B窗口...
  • C#委托理解(1)

    2018-03-20 16:08:31
    # 委托 ### 1、理解 ##(1)委托类型用于定义和相应应用程序中的回调;(2)使用回调,程序员可以使一个函数 返回报告给(即回调)另一个函数;(3)委托是类型安全的对象,它指向程序中另一个以后会被调用的的方法...
  • C# 委托和事件 练习

    千次阅读 2017-03-01 19:13:10
    using System; using System.Collections.Generic; using System.Linq;... * 委托与事件练习 * * 表、响铃、按钮 * * 表时间从0开始,走到6就要响铃 * 响铃后输入n按回车,模拟按掉闹铃。 * 参考资料:http
  • C# 委托及Lambda 表达式

    2019-04-19 17:36:36
    Delegate 委托 委托声明:public delegate int MyDelegate (string s); 用delegate关键字定义委托,它是对特定返回类型和参数的方法的抽象,是你定义的一种新数据类型,它与int、class是一样的都是数据类型。符合...
  • C#委托与代理模式

    千次阅读 热门讨论 2014-03-09 11:13:09
    在设计模式的学习过程中,委托是一个不容易理解的知识点。尤其是在学完代理模式之后,就更不知道什么是什么了。下面分别看一下各自的实例,来看一下这两者有什么区别。  委托是一种引用方法的类型。一旦为委托...
1 2 3 4 5 ... 20
收藏数 71,098
精华内容 28,439
关键字:

c#委托