一、委托的定义和基本使用
委托的官方定义如下:
委托类型表示对具有特定参数列表和返回类型的方法的引用。 通过委托,可以将方法视为可分配给变量并可作为参数传递的实体。 委托类似于其他一些语言中的函数指针概念,但与函数指针不同的是,委托不仅面向对象,还类型安全。https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/delegates
委托是官方给我们一个解耦程序逻辑的的一种手段,我告诉了你我这个这个方法需要零或多个类型的入参和返回值的委托对象,你只需要传进来这样一个匹配规则的方法就可以了,程序会按照你方法逻辑做一些你想要执行的代码。下面给出简单的示例
public delegate double SampleDelegate(double db); static void Main(string[] args) { TestDelegate(db => db * 2, 4.5); Console.ReadLine(); } public static void TestDelegate(SampleDelegate sampleDelegate, double db) { Console.Write($"执行委托后结果为:{sampleDelegate.Invoke(db)}"); }
最后程序回返回执行结果9。
委托告诉了我们,我不需要关心具体实现只需要你匹配我的规则我就执行,为了方便扩展,我们可以往往会创建事件来丰富扩展,事件是和委托基本是连为一体的,因为创建事件就需要以来委托。事件的定义如下:
和委托类似,事件是后期绑定机制。 实际上,事件是建立在对委托的语言支持之上的。
事件是对象用于(向系统中的所有相关组件)广播已发生事情的一种方式。 任何其他组件都可以订阅事件,并在事件引发时得到通知。
通过订阅事件,还可在两个对象(事件源和事件接收器)之间创建耦合。 需要确保当不再对事件感兴趣时,事件接收器将从事件源取消订阅。示例代码如下
public delegate double SampleDelegate(double db); public static event SampleDelegate SampleEvent; static void Main(string[] args) { var delegate1= new SampleDelegate(db => db * 2); var delegate2 = new SampleDelegate(db => db * 2); SampleEvent += delegate1; SampleEvent += delegate2; SampleEvent -= delegate2; if (SampleEvent == null) throw new Exception("event SampleEvent is null"); SampleEvent(4.5); Console.ReadLine(); }
通过事件我们可以扩展多个委托绑定到事件上来批量执行。
二、委托的扩展作用
1、使用异步方式调用同步方法
public delegate void AsyncDelegate(); static void Main(string[] args) { Console.WriteLine("执行委托前 Main方法的执行线程ID: {0}", Thread.CurrentThread.ManagedThreadId); var testdelegate = new AsyncDelegate(TestDelegate); testdelegate.BeginInvoke(null, null); Console.WriteLine("执行委托后 Main方法的执行线程ID: {0}", Thread.CurrentThread.ManagedThreadId); Console.ReadLine(); } public static void TestDelegate() { Console.WriteLine("TestDelegate方法的执行线程ID: {0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000); Console.WriteLine($"空闲1秒后,方法的执行线程ID {Thread.CurrentThread.ManagedThreadId}."); }
测试结果为:
执行委托前 Main方法的执行线程ID: 1 执行委托后 Main方法的执行线程ID: 1 TestDelegate方法的执行线程ID: 3 空闲1秒后,方法的执行线程ID 3.
提醒:在新的.net core环境下已经不支持这种方式创建异步!推荐使用成熟的Task async await的方式来使用。