委托,在C#编程中占有极其重要的地位,委托可以将函数封装到委托对象中,并且多个委托可以合并为一个委托,委托对象则可以像普通对象一样被存储、传递,之后在任何时刻进行调用,因此,C#中函数回调机制的实现基本上依赖于委托。C#的delegate关键字用于声明委托,它具有将声明委托类型映射到System.Delegate类的能力,System.Delegate类位于mscorlib.dll中,是.NET的基础核心类之一。使用delegate关键字声明一个委托,实质上创建了System.Delegate的派生类,因此委托类型并非结构体也不是其它类型,它是一个类。一个委托对象也就是一个类的实例。以下是Delegate类的声明:

public abstract class Delegate

Delegate是所以委托类型的基类,C#中的多播委托实际上是MulticastDelegate类,它是System.Delegate的派生类,而本文中介绍的Action、Func泛型委托实际上都是MulticastDelegate类的派生类型。C#中当我们使用delegate关键字声明一个委托类型时,实际上是由C#编译器根据我们声明时的方法签名帮助我们生成一个与签名匹配的,派生自MulticastDelegate的类。在泛型大量应用之前,我们写一个C#程序的时候可能会使用delegate关键字声明许多委托类型,因为这些类型都对应于不同的方法签名。通过Visual Studio的对象浏览器查看mscorlib可以看到这两种重要的泛型委托:

其中除了Action之外,其它的委托都是泛型的,其实就是一些泛型类。这便是.NET核心库中全部的泛型委托了。这些泛型委托分为Func、Action中,它们借助于泛型特性,可以替代C#中几乎所有的委托类型,也就是说一般情况下,在我们的程序中不必再声明任何新的委托类型,就可以包装所有的函数了。比如我们有两个方法:

public static void OtputString(string str)
{
Console.WriteLine(str);
} public static int Add(int a, int b)
{
return a + b;
}

Func泛型委托与Action相比即多出了一个TResult类型参数,用于函数具有返回值的情况,Action泛型委托用于没有返回值的函数。当我们要获得这两个方法的委托对象时这样变可以了:

var action = new Action<string>(OtputString);
action("OutputString Invoked!");
var func = new Func<int, int, int>(Add);
var sum = func(3, 5);
Console.WriteLine(sum);

可以看见,当我们将具有返回值的函数包装成委托对象时使用Func委托,如果函数没有返回值则使用Action,核心库提供的泛型委托类型参数最短的为0,最长的为8个。因此,Action及其泛型委托可以匹配无返回值、参数数量为0到8的任何函数。同样的,Func泛型委托可以匹配由返回值、参数数量在0到8个的任何函数。一般情况下,程序中函数的参数数量都不会超过8个,即使超过8个,我们可以声明新的泛型委托类型来应对

delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9);

使用这些泛型委托不会有任何的性能损失,使得程序中委托的使用风格保持一致。唯一的缺点就是类型的名称无法表达具体的用途,举例来讲EventHandler委托,我们一看名字就知道这是用于事件处理的委托。而使用Action<object,EventArgs>委托我们则无法从名称看出这种类型的委托是何种用途。

泛型委托有替代所有其它委托的能力,到底应该使用泛型委托还是普通委托、何时使用、在哪种情况下用,可能每个人都有不同的简介,不过说到底,泛型委托能统一程序代码风格以及随处方便使用等优点是非常显著的。

.NET中的Action及Func泛型委托的更多相关文章

  1. 使用.NET中的Action及Func泛型委托

          委托,在C#编程中占有极其重要的地位,委托可以将函数封装到委托对象中,并且多个委托可以合并为一个委托,委托对象则可以像普通对象一样被存储.传递,之后在任何时刻进行调用,因此,C#中函数回调 ...

  2. Aap.Net中的Action和Func委托

    前言 最近在阅读某开源框架源码的时候,发现作者在其中运用了很多Action委托和Func委托,虽然我之前在项目中也有一些对委托的实操,但还是免不了长时间的不用,当初消化的一些委托基础都遗忘了...索性 ...

  3. 委托、Action泛型委托、Func泛型委托、Predicate泛型委托的用法

    一.举一委托场景:天气很热,二狗子想去买瓶冰镇可乐,但是二狗子很懒,于是他想找个人代他去,于是要有个代理人. 创建代理人之前先定义委托:public delegate string BuyColaDe ...

  4. C#中的Action和Func和Predicate

    一.[action<>]指定那些只有输入参数,没有返回值的委托 用了Action之后呢: 就是相当于省去了定义委托的步骤了. 演示代码: using System; using Syste ...

  5. 委托delegate 泛型委托action<> 返回值泛型委托Func<> 匿名方法 lambda表达式 的理解

    1.使用简单委托 namespace 简单委托 { class Program { //委托方法签名 delegate void MyBookDel(int a); //定义委托 static MyB ...

  6. C#中的Action<>和Func<>

    其实他们两个都是委托[代理]的简写形式. 一.[action<>]指定那些只有输入参数,没有返回值的委托 Delegate的代码: public delegate void myDeleg ...

  7. 在.net2.0中实现Action和Func方法

    由于这两个是在.net3.5中新加入的特性,所以我们需要自己写一下. 格式如下: delegate void Action();        delegate void Action<T, T ...

  8. Action<T>和Func<T>委托事例

    Action<T>和Func<T>委托事例 using System; //除了为每个参数和返回类型定义一个新委托类型之外,还可以使用Action<T>和Func& ...

  9. C#高级功能(三)Action、Func,Tuple

    Action和Func泛型委托实际上就是一个.NET Framework预定义的委托,3.5引入的特性.基本涵盖了所有常用的委托,所以一般不用用户重新声明. Action系列泛型委托,是没有返回参数的 ...

随机推荐

  1. 实时查看linux网卡流量

    将下列脚本保存为可执行脚本文件,比如叫traff.sh. 1.本脚本可自定义欲查看接口,精确到小数,并可根据流量大小灵活显示单位. 2.此脚本的采集间隔为1秒. 3.此脚本不需要额外再安装软件,可在急 ...

  2. w-WAITING---

    <p id="w_last" style="color: red; font-size: 6em;">w-WAITING---</p>& ...

  3. Flink Internals

    https://cwiki.apache.org/confluence/display/FLINK/Flink+Internals   Memory Management (Batch API) In ...

  4. javaee基本环境搭建

    安装包 安装jdk :D:\Program Files\Java\jdk1.7.0_17 下载tomcat:E:\apache-tomcat-6.0.36 下载maven:E:\apache-mave ...

  5. php 通过exec 创建git分支失败

    今天给我们自己的发布系统增加一个新建分支的功能,操作比较简单,但是使用php执行shell命令的时候总是无法push分支到远程,但是登陆服务器执行却是可以的 新建分支命令如下 git fetch -- ...

  6. json格式的转换为json字符串函数

    function toJSON(object){ var type = typeof object; if ('object' == type) { if (Array == object.const ...

  7. mysql创建外键出错(注意数据库表字段排序)

    1.  两个字段的类型或者大小不严格匹配.例如,如果一个是int(10),那么外键也必须设置成int(10),而不是int(11),也不能是tinyint.另外,你还必须确定两个字段是否一个为 sig ...

  8. BLE-NRF51822教程17-DFU使用手机升级

    演示的工程是 [application]    nRF51_SDK_10.0.0_dc26b5e\examples\ble_peripheral\ble_app_hrs\pca10028\s110_w ...

  9. Java HashMap、LinkedHashMap

    如果需要使用的Map中的key无序,选择HashMap:如果要求key有序,则选择TreeMap. 但是选择TreeMap就会有性能问题,因为TreeMap的get操作的时间复杂度是O(log(n)) ...

  10. JNI字段描述符(转)

    转载自http://fgsink.blog.163.com/blog/static/16716997020124310169911/ “([Ljava/lang/String;)V” 它是一种对函数返 ...