zoukankan      html  css  js  c++  java
  • c# 委托

    前言

    打算整理c# 代码简化史系列,所以相关的整理一下。

    什么是委托,官网这样介绍。

    同样委托有下面属性:

    委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。 在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。 你可以通过委托实例调用方法。

    委托类似于 C++ 函数指针,但委托完全面向对象,不像 C++ 指针会记住函数,委托会同时封装对象实例和方法。

    委托允许将方法作为参数进行传递。

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

    委托可以链接在一起;例如,可以对一个事件调用多个方法。

    方法不必与委托类型完全匹配。

    C# 2.0 版引入了匿名方法的概念,可以将代码块作为参数(而不是单独定义的方法)进行传递。 C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。 匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。 这些功能现在统称为匿名函数。

    正文

    下面就一以来介绍下面的属性吧。

    第一句怎么理解呢?委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。

    举个例子:
    public delegate int PerformCalculation(int x, int y);

    class Program
    {
    	public delegate int PerformCalculation(int x, int y);
    	static void Main(string[] args)
    	{
    		PerformCalculation p = new PerformCalculation(add);
    	}
    	public static int add(int x, int y)
    	{
    		return x + y;
    	}
    }
    

    public delegate int PerformCalculation(int x, int y) 是定义了一个委托类型,然后呢,我们可以实例化它。

    我们可以实例化传入对应的方法,而不是传入x和y,这是和普通实例不一样的,初学的时候可以理解为对方法的封装。

    那么调用的时候就是 p.Invoke(1,2);,通过invoke方法来调用,当然也可以p()来调用,这是语法糖。

    p.invoke 会触发当前封装好的方法,其实本质是指针,这个后续系列中会展示。

    第二句话,其实本质就是指针哈,只是对其进行了封装,后续系列。

    第三句话,如下:
    public static int hasCallBack(PerformCalculation performCalculation)
    {
    return performCalculation.Invoke(1,2);
    }

    第四句话:委托可以链接在一起;

    PerformCalculation p = new PerformCalculation(add);
    PerformCalculation p2 = new PerformCalculation(sub);
    p += p2;

    也可以简写:
    p += sub; 本质一致,只是操作自定义里面做的判断类型了。在c#1版本中用的还是方法连接,现在版本中删除了。

    同样PerformCalculation p =add;这是可以这样写。

    那么这里有一个问题,既然可以连接多个委托,那么返回的结果是哪个呢?返回的是最后一个结果,如果运行正常得到话,如果不正确会报错,且当前运行方法后面的不会运行,这也是使用委托非常值得关注的地方。

    第五句话 方法不必与委托类型完全匹配

    这个指的是逆变和协变

    协变:

    本示例演示如何将委托与具有返回类型的方法一起使用,这些返回类型派生自委托签名中的返回类型。 DogsHandler 返回的数据类型属于 Dogs 类型,它派生自委托中定义的 Mammals 类型。

    发一个官网的例子:

    class Mammals {}  
    class Dogs : Mammals {}  
      
    class Program  
    {  
        // Define the delegate.  
        public delegate Mammals HandlerMethod();  
      
        public static Mammals MammalsHandler()  
        {  
            return null;  
        }  
      
        public static Dogs DogsHandler()  
        {  
            return null;  
        }  
      
        static void Test()  
        {  
            HandlerMethod handlerMammals = MammalsHandler;  
      
            // Covariance enables this assignment.  
            HandlerMethod handlerDogs = DogsHandler;  
        }  
    }
    

    然后是逆变:

    官网例子:

    本示例演示如何将委托与具有参数的方法一起使用,这些参数的类型是委托签名参数类型的基类型。 通过逆变可以使用一个事件处理程序而不是多个单独的处理程序。

    下面的示例使用两个委托:

    public delegate void KeyEventHandler(object sender, KeyEventArgs e)

    public delegate void MouseEventHandler(object sender, MouseEventArgs e)

    然后可以这样:

    // Event handler that accepts a parameter of the EventArgs type.  
    private void MultiHandler(object sender, System.EventArgs e)  
    {  
        label1.Text = System.DateTime.Now.ToString();  
    }  
      
    public Form1()  
    {  
        InitializeComponent();  
      
        // You can use a method that has an EventArgs parameter,  
        // although the event expects the KeyEventArgs parameter.  
        this.button1.KeyDown += this.MultiHandler;  
      
        // You can use the same method
        // for an event that expects the MouseEventArgs parameter.  
        this.button1.MouseClick += this.MultiHandler;  
      
    }
    

    这里简单说一下逆变和协变的区别,协变是作用域返回值,且是子类 赋值给父类,这看起来很和谐,因为子类继承父类。

    逆变就是作用于参数,然后是父类赋值给子类,这其实就有点逆反的作用。

    但是如果你们去看il语言你们就不觉得奇怪了,因为他们其实是编译器帮助做了转换,这节只是简单的做下介绍。

    然后最后一句是就是后面一章用来汇总的历史的,所以就不介绍了。

  • 相关阅读:
    一些有用的DNN方法
    将VB.Net反编译时StringType.StrCmp用C#中的函数string.Compare替换
    接一个DNN安装时的未知错误,终于找到了原因
    这是用performancing for firefox编写的blog
    这是用word2007发表的blog
    一个DNN安装时的未知错误
    后端——框架——切面框架——aop——Pointcut表达式
    Metroid Prime Chs 20101004
    第一财经周刊:书店的黄昏
    这年头连萝卜都靠不住了
  • 原文地址:https://www.cnblogs.com/aoximin/p/13940125.html
Copyright © 2011-2022 走看看