C# 知识回顾 - 委托 delegate

【博主】反骨仔    【原文】http://www.cnblogs.com/liqingwen/p/6031892.html

目录

What's 委托

  delegate 一种自定义的引用类型,它包含了特定的参数列表和返回类型。

  使用委托时,只需要对应的方法的签名和返回类型兼容即可,无论是实例方法,抑或是静态方法。通过调用委托的实例就相当于调用方法本身,因为委托存储的是一个方法列表,调用委托的实例就相当于依次调用方法列表的内容。委托它将方法作为参数进行传递给了其它方法,我们常用的事件处理程序就是通过委托调用的方法,也是一种观察者模式的体现。

  下面的示例演示了一个委托声明:

public delegate int Del(int x, int y);

  

  使用委托的要求是:方法签名与返回类型兼容。可以是静态方法,也可以是实例方法。  

  【备注】方法的签名不包括返回值。

委托的特点

  • 类型安全,类似于 C 和 C++ 中的函数指针。

  • 可将方法作为参数进行传递。

  • 可用于定义回调方法。

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

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

使用委托

  委托,一种类型,它是安全的,自定义的,委托的名称就决定了这个委托是什么类型。

    //该委托可以封装 “,参数类型 string,返回类型 void” 的方法
public delegate void MyDel(string message);

  委托的实例对象通常使用两种方式进行构建,直接使用类的方法名,或者使用 Lambda 表达式,当然匿名方法也可以。

  在调用委托的时刻,我们将传递到委托的参数会继续传递到委托列表的方法中。如果委托列表中包含返回值的话,会将最后一个返回值返回给调用方。也就是该委托对象调用完毕的返回值。

     //该委托名为 MyDel,可以封装 “参数类型 string,返回值类型 void” 的方法
public delegate void MyDel(string message); class Program
{
static void Main(string[] args)
{
//实例化委托
MyDel del = Print;
//调用委托
del("Hi"); Console.Read();
} /// <summary>
/// 打印文本
/// </summary>
/// <remarks>这是一个可用于 MyDel 委托的方法</remarks>
/// <param name="message"></param>
private static void Print(string message)
{
Console.WriteLine(message);
}
}

  委托的关键字是 delegate,它派生自 Delegate 类,也是 sealed,即密封类,不能作为基类再继续派生。

  异步回调:允许以方法的形式作为参数形式进行传递,并在稍后进行该委托的调用。通过这个形式使用的委托,调用方不需要知道方法的具体实现,只是简单的把它当做一个功能即可,这类似接口的封装。

 
  简单的异步回调方法演示:
     class Program
{
static void Main(string[] args)
{
MyDel del = Print;
CallbackMethod(, , del); //将委托传递到 CallbackMethod 方法 Console.Read();
} /// <summary>
/// 回调方法
/// </summary>
/// <param name="m"></param>
/// <param name="n"></param>
/// <param name="del"></param>
private static void CallbackMethod(int m, int n, MyDel del)
{
del((m + n).ToString());
} private static void Print(string message)
{
Console.WriteLine(message);
}
}

  在这里的 CallbackMethod 作用是,调用委托,因为它包含的是 Print() 方法的调用,所以只需要传递对应的 string 类型作为参数即可。

  我们在创建委托的时候,你可以选择使用的是实例方法或者是静态方法。当你使用的是实例方法时,该委托对象会同时引用该实例的对象及它的方法。委托并不关心应用引用对象的类型,它关心的是,方法签名和返回值兼容,即可。不过,如果你创建委托对象包含的是静态方法的时候,它是只引用该方法的。

  使用 += 可以把多个方法添加到一个委托对象的调用列表中,调用一次委托,相当于一次性调用一堆方法。

     //该委托可以封装 “名 MyDel,参数类型 string,返回值类型 void” 的方法
public delegate void MyDel(string message); class MyClass
{
public void Print1(string message)
{
Console.WriteLine($"{message} - {nameof(Print1)}");
} public void Print2(string message)
{
Console.WriteLine($"{message} - {nameof(Print2)}");
}
} class Program
{
static void Main(string[] args)
{
var myClass = new MyClass();
MyDel del1 = myClass.Print1;
MyDel del2 = myClass.Print2;
MyDel del3 = Print; var del = del1 + del2;
del += del3; //这里使用 +=
del("Hi!"); Console.Read();
} private static void Print(string message)
{
Console.WriteLine($"{message} - {nameof(Print)}");
}
}

  委托对象 del,他内部存储的是一个包含三个方法的调用列表(Print1、Print2 和 Print),在你调用 del 对象时,调用列表中的方法会依次调用。

  

  多播委托:一个委托对象调用多个方法,使用 +=。

  若要从委托对象的调用列表中移除方法,需要使用 -=。

         static void Main(string[] args)
{
var myClass = new MyClass();
MyDel del1 = myClass.Print1;
MyDel del2 = myClass.Print2;
MyDel del3 = Print; var del = del1 + del2;
del += del3; //使用 +=
del("Hi!"); Console.WriteLine("======分割线======"); del -= del2; //使用 -=
del("Hi!"); Console.Read();
}

  你也可以编写一些方法获取调用列表中方法的数量:

         static void Main(string[] args)
{
var myClass = new MyClass();
MyDel del1 = myClass.Print1;
MyDel del2 = myClass.Print2;
MyDel del3 = Print; var del = del1 + del2;
del += del3; //使用 +=
//del("Hi!"); var count = del.GetInvocationList().Length; //获取委托调用列表中方法的数量
Console.WriteLine(count); Console.WriteLine("======分割线======"); del -= del2; //使用 -=
//del("Hi!"); count = del.GetInvocationList().Length; //获取委托调用列表中方法的数量
Console.WriteLine(count); Console.Read();
}

  多播委托派生自 MulticastDelegate,也是继承自 Delegate的,常用于事件处理中。

传送门

  《C# 知识回顾 - 序列化》

  《C# 知识回顾 - 表达式树 Expression Trees》


【参考】https://msdn.microsoft.com/zh-cn/library/windows/apps/ms173171(v=vs.120).aspx

【参考】微软官方文档

[C#] C# 知识回顾 - 委托 delegate的更多相关文章

  1. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  2. C#基础知识回顾--委托事件

    在上一篇看到他我一下子就悟了(续)---委托,被人狂喷.说写的太空,没有什么内容之类的.所以准备在这里重写下,不过还是按着以前的方式尽量简单的写.这里我们以打篮球为例. 第一步:首先,其他对象订购事件 ...

  3. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  4. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  5. [C#] C# 知识回顾 - 学会使用异常

    学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...

  6. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

  7. [.NET] C# 知识回顾 - Event 事件

    C# 知识回顾 - Event 事件 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6060297.html 序 昨天,通过<C# 知识回顾 - ...

  8. [.NET] C# 知识回顾 - 事件入门

    C# 知识回顾 - 事件入门 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6057301.html 序 之前通过<C# 知识回顾 - 委托 de ...

  9. C# 知识回顾 - 装箱与拆箱

    装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 生活中的装箱与拆箱    我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃> ...

随机推荐

  1. EasyMesh - A Two-Dimensional Quality Mesh Generator

    EasyMesh - A Two-Dimensional Quality Mesh Generator eryar@163.com Abstract. EasyMesh is developed by ...

  2. TODO:GitHub创建组织的步骤

    TODO:GitHub创建组织的步骤 使用GitHub进行团队合作,写这个步骤主要作用是为了OneTODO作为一个团队组织进行代码的分享,让更多人来参与. 使用帐号.密码登录GitHub 2.右上角加 ...

  3. Linux CentOS 配置JDK环境

    一.下载JDK 下载JDK的方式有两种: 1.Linux中使用wget下载 1.使用命令安装wget yum install wget 2.下载 wget 'http://download.oracl ...

  4. 清空Github上某个文件的历史版本

    title: 清空Github上某个文件的历史版本 author: 青南 date: 2015-01-08 16:04:53 categories: [经验] tags: [Github,histor ...

  5. spring boot 实战:我们的第一款开源软件

    在信息爆炸时代,如何避免持续性信息过剩,使自己变得专注而不是被纷繁的信息所累?每天会看到各种各样的新闻,各种新潮的技术层出不穷,如何筛选出自己所关心的? 各位看官会想,我们是来看开源软件的,你给我扯什 ...

  6. JQuery实现表格的增加行和删除行

    利用JQuery实现datatables插件的增加和删除行操作 在学习过程中遇到了这个利用JQuery对表格行的增加和删除,特记录下来以供初学者参考. 下面是主要的代码: <meta http- ...

  7. iosselect:一个js picker项目,在H5中实现IOS的select下拉框效果

    具体文档和demo可以访问github:https://github.com/zhoushengmufc/iosselect 移动端浏览器对于select的展示样式是不一致的,ios下是类似原生的pi ...

  8. http status code

    属于转载 http status code:200:成功,服务器已成功处理了请求,通常这表示服务器提供了请求的网页 404:未找到,服务器未找到 201-206都表示服务器成功处理了请求的状态代码,说 ...

  9. 新技术≠颠覆:CIO 要有战略耐心

    新技术≠颠覆:CIO 要有战略耐心 大数据,云时代,互联网思维, 物联网--最近一两年,这些字眼一次次地出现在各种大大小小的CIO会议上和他们的私下交流圈子里,作为对新技术最敏感的人群,一方面他们迫切 ...

  10. Android之ContentProvider数据存储

    一.ContentProvider保存数据介绍 一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProvider是以类似数据库中表的方式将数 ...