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语言你们就不觉得奇怪了,因为他们其实是编译器帮助做了转换,这节只是简单的做下介绍。

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

posted @ 2020-11-07 10:45  敖毛毛  阅读(200)  评论(0编辑  收藏  举报