• C#高级编程笔记 Delegate 的粗浅理解 2016年9月 13日


    Delegate [重中之重] 委托

    定义一:(参考)http://www.cnblogs.com/zhangchenliang/archive/2012/09/19/2694430.html

    • 完全可以把delegate理解成C中的函数指针。
      它允许你传递一个 类A 的 方法m 给另一个 类B 的对象,使得 类B 的对象能够调用这个 方法m ,说白了就是可以把方法当作参数传递。
      不过delegate和函数指针还是有点区别的,delegate有许多函数指针不具备的优点。
          首先:函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。
          在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。
          其次,与函数指针相 比,delegate是面向对象、类型安全、可靠的受控(managed)对象。
      也就是说,runtime能够保证delegate指向一个有效的方法, 你无须担心delegate会指向无效地址或者越界地址。

    个人理解(利用原博主的源代码进行分析)

    • 例一 
       1 namespace Jandar.Test.Yinxi{
       2     class DelegateTest{
       3         public delegate void CompareDelegate(int a,int b);
       4 
       5         public static void Compare(int a,int b){
       6             System.Console.WriteLine((a>b).ToString());
       7         }
       8         public static void Main(string[] args){
       9             CompareDelegate cd=new CompareDelegate(Compare);
      10             cd(1,2);
      11 
      12             //Compare(5,4);和上面两行的执行结果是一样的。
      13         }
      14     }
      15 }

    首先我们来分析一下 例一 的堆栈调用过程

    1 CompareDelegate cd=new CompareDelegate(Compare);

    因为 CompareDelegate 是一个引用类型。所以这步执行的是在 堆中创建一个引用类型对象

    接下来执行 cd(1,2);

    我以图解来描述一下

    接下来的例二和上例一差不多 ,以下也给出源代码

    •  1 namespace Jandar.Test.Yinxi
       2 {
       3     public delegate void MyTestDelegate(int i);//use like interface 
       4 
       5     public class DelegateTest
       6     {
       7         public static void Main()
       8         {
       9             RecieveDelegateArgsFuns(new MyTestDelegate(DelegateFunction));
      10         }
      11         public static void RecieveDelegateArgsFuns(MyTestDelegate func)
      12         {
      13             func(21);
      14         }
      15         public static void DelegateFunction(int i)
      16         {
      17             System.Console.WriteLine("传来的参数{0}",i);
      18         }
      19     }
      20

    附上手稿

    •               

    通过理解 .Net 中的OnClick 机制 来深入理解 Delegate 

    C#中的事件处理实际上是一种具有特殊签名的 delegate

    public delegate void MyEventHandler(object sender, MyEventArgs e);

    其中的两个参数,sender代表事件发送者,e是事件参数类。MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从 System.EventArgs类派生。当然,如果你的事件不含参数,那么可以直接用System.EventArgs类作为参数。(例子解释直接在代码中)

     1  using System;
     2  namespace Jandar.Test.YinXi
     3  {
     4      public class ButtonClickArgs : EventArgs
     5      {
     6          public string Clicker;//用来显示 操作对象。
     7      }
     8      public class MyButton
     9      {
    10          public delegate void ClickHandle(object sender, ButtonClickArgs e);//声明一个delegate的类型
    11  
    12          public event ClickHandle OnClick;//定义事件,类型为 delegate 的ClickHandle对象;
    13          public void Click()
    14          {
    15              OnClick(this, new ButtonClickArgs() { Clicker = "H" });////相当于 onClick中自带的 Invoke()方法,类似与 OnClick.Invoke(
    16 //this, new ButtonClickArgs() { Clicker = "H" }
    17          }
    18      }
    19      public class Program
    20      {
    21          public static void Main(string[] args)
    22          {
    23              MyButton btn = new MyButton();
    24              btn.OnClick += new MyButton.ClickHandle(btn_OnClick);//注册时间,把btn_OnClick 方法绑定到 委托事件中。
    25        btn.Click();//进行调用
    26          }
    27          public static void btn_OnClick(object sender, ButtonClickArgs e)
    28          {
    29              Console.WriteLine("Hello,MyWorld!");
    30          }
    31      }
    32 }

    定义二:(参考)http://www.cnblogs.com/idior/articles/100666.html

    • 将Delegate理解为接口,只有一个方法的接口,这样最容易理解。这个方法只有声明,没有实现,实现在别的类。(实际上应该把它看作函数指针,不过接口更容易理解些。)
      在你的类中有一个Delegate就相当于有一个接口。通过这个接口你可以调用一个方法,而这个方法在别的类定义,由别的类来干。

    定义三:(参考)http://www.cnblogs.com/hyddd/archive/2009/07/26/1531538.html

    • Delegate中文翻译为“委托”。Msdn中对Delegate的解释如下:
      
      C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,
      而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。
     1 using System;
     2 namespace Jandar.Test.YinXi{
     3 
     4     class TestDelegate
     5     {
     6         public delegate void DelegateMethod();  //声明了一个Delegate Type
     7 
     8         public DelegateMethod delegateMethod;   //声明了一个Delegate对象
     9 
    10         public static void StaticMethod()   
    11         {
    12             Console.WriteLine("Delegate a static method");
    13         }
    14 
    15         public void NonStaticMethod()   
    16         {
    17             Console.WriteLine("Delegate a non-static method");
    18         }
    19 
    20         public void RunDelegateMethods()
    21         {
    22             if(delegateMethod != null){
    23                 Console.WriteLine("---------");
    24                 delegateMethod.Invoke();  //运行 delegateMethod所搭载的函数  
    25                 Console.WriteLine("---------");
    26             }
    27         }
    28     }
    29 
    30     class Program
    31     {
    32         static void OtherClassMethod(){
    33             Console.WriteLine("Delegate an other class's method");
    34         }
    35 
    36         static void Main(string[] args)
    37         {
    38             var test = new TestDelegate();
    39             test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
    40             test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
    41             test.delegateMethod += Program.OtherClassMethod;
    42             test.RunDelegateMethods();
    43         }
    44     }
    45  }

    上面这个例子我觉得挺好的,体现了定义一种的 解释

    它允许你传递一个 类A 的 方法m 给另一个 类B 的对象,使得 类B 的对象能够调用这个 方法m ,说白了就是可以把方法当作参数传递。
  • 相关阅读:
    动态SQL的注意
    关于数据库抛出异常:Incorrect string value: 'xE1x...' for column '字段名' at row 1 问题的解决方法
    让.bashrc文件在终端自动生效
    期中考试题
    RAP、Mock.js、Vue.js、Webpack
    全局变量变为局部变量 & MVC思想
    用 JS + LeanCloud 给网页添加数据库(留言功能)
    闭包的使用
    从发请求到AJAX到同源政策
    从实现HTML页面局部刷新到JSONP
  • 原文地址:https://www.cnblogs.com/xiyin/p/5869182.html
Copyright © 2020-2023  润新知