一、委托Delegate

一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本的数据类型(或者没有参数),比如


public void HelloWorld() 
{
    Console.WriteLine("Hello World!");
}
public void HelloWorld(string name) 
{
    Console.WriteLine("Hello ,{0}!", name);
}

但是有些时候,我们希望把一个方法本身当做参数传递给另一个方法,比如

myObject.callMethod(HelloWorld);

在没有委托之前,这是一件极困难的事情,委托出现以后,这就是一件很容易的事情了,简单点讲:委托就是一种能把方法当做参数来使用的类型--当然这个定义跟官方的解释比起来极不严密,但易于理解

要点:
1.委托是一种类型(跟string,int,double...一样是.net的一种基本类型)
2.委托的定义必须与最终被调用的方法保持签名一致

比如:下面代码中的

delegate void D1(); 与 static void HelloWorld1(),我们抛开前面的类型关键字delegate与static,他们的签名都是void X()
void D2(string myName);与void HelloWorld2(string name); void HelloWorld3(string name);它们的签名格式都是 void X(string Y)

3.委托的好处之一在于可以保持签名格式不变的情况下,动态调用不同的处理逻辑(即不同的方法)

想想系统控件中的Button类,系统并不知道按钮按下去时到底会执行怎么样的逻辑(点击后的处理,每个项目可能都不一样,完全由需求决定),但是我们知道每个Button都有一个Click(object sender, EventArgs e)这样的东东,没错,就是委托(当然封装成了另一种衍生类型event),就是这种设计保证了统一的格式,不管你实际开发中想如何处理点击后的逻辑,只要按这个统一的签名来就行了
完整代码演示:


using System;
namespace ActionStudy
{
    class Program
    {
       
        delegate void D1();
        delegate void D2(string myName);         static void Main(string[] args)
        {
            D1 d1 = new D1(HelloWorld1);
            d1();             D2 d2 = new D2(HelloWorld2);
            d2("Jimmy");             d2 = new D2(HelloWorld3);
            d2("杨俊明");                         Console.Read();         }         static void HelloWorld1()
        {
            Console.WriteLine("Hello World!");
        }         static void HelloWorld2(string name) 
        {
            Console.WriteLine("Hello,{0}!", name);
        }         static void HelloWorld3(string name)
        {
            Console.WriteLine("你好,{0}!", name);
        }
    }
}

二 、匿名方法(.net2.0开始支持)

在“一、委托Delegate”的演示代码中,我们看到委托调用方法前,至少得先定义一个签名相同的方法,然后才能由委托调用(哪怕是只有一行代码的方法),好象有点烦哦,想偷懒,ok,没问题


using System;
namespace ActionStudy
{
    class Program
    {         delegate void D1();
        delegate void D2(string myName);         static void Main(string[] args)
        {
            D1 d1 = delegate
            {
                Console.WriteLine("Hello World!");
            };
            d1();             D2 d2 = delegate(string name)
            {
                Console.WriteLine("Hello,{0}!", name);
            };             d2("Jimmy");             d2 = delegate(string name)
            {
                Console.WriteLine("你好,{0}!", name);
            };             d2("杨俊明");             Console.Read();         }
    }
}

运行效果完全相同,只是省去了方法的单独定义部分

到了.net 3.0这种偷懒的作风更夸张,看下面的代码(利用了Lambda表达式)


using System;
namespace ActionStudy
{
    class Program
    {         delegate void D1();
        delegate void D2(string myName);         static void Main(string[] args)
        {                        D1 d1 = () => { Console.WriteLine("Hello World!"); };
            d1();             D2 d2 = (string name) => { Console.WriteLine("Hello,{0}!", name); };
            d2("Jimmy");             d2 = (string name) => { Console.WriteLine("你好,{0}!", name); };
            d2("杨俊明");             Console.Read();         }
    }
}

运行效果仍然没变,初次接触者可能感觉很怪,其实我也觉得怪,不过很多大牛们都喜欢这样用,所以至少还是要能看得懂,否则别人会说"你 Out了" :)
三、Action

Action的本质就是委托,看它的定义:


namespace System
{
    // 摘要:
    //     Encapsulates a method that takes no parameters and does not return a value.
    public delegate void Action();
} namespace System
{
    // 摘要:
    //     Encapsulates a method that takes a single parameter and does not return a
    //     value.
    //
    // 参数:
    //   obj:
    //     The parameter of the method that this delegate encapsulates.
    //
    // 类型参数:
    //   T:
    //     The type of the parameter of the method that this delegate encapsulates.
    public delegate void Action<T>(T obj);
}

当然,还有Action<T1,T2>乃至Action<T1,T2,T3,T4>参数个数从2到4的类型,不过定义都差不多

简单点讲,Action是参数从0到4,返回类型为void(即没有返回值)的委托


using System;
namespace ActionStudy
{
    class Program
    {         static Action A1;
        static Action<string> A2;
                static void Main(string[] args)
        {
            A1 = new Action(HelloWorld1);
            A1();             A2 = new Action<string>(HelloWorld2);
            A2("Jimmy");             A2 = (string name) => { Console.WriteLine("你好,{0}!", name); };
            A2("杨俊明");             A2 = delegate(string name) { Console.WriteLine("我就是委托,{0} 你说对吗?", name); };
            A2("菩提树下的杨过");                       Console.Read();         }         static void HelloWorld1()
        {
            Console.WriteLine("Hello World!");
        }         static void HelloWorld2(string name)
        {
            Console.WriteLine("Hello,{0}!", name);
        }        
    }    
}

四、Func

Func其实也是一个"托"儿,呵呵,不过这个委托是有返回值的。看下定义就知道了:


namespace System
{
    // 摘要:
    //     Encapsulates a method that has no parameters and returns a value of the type
    //     specified by the TResult parameter.
    //
    // 类型参数:
    //   TResult:
    //     The type of the return value of the method that this delegate encapsulates.
    //
    // 返回结果:
    //     The return value of the method that this delegate encapsulates.
    public delegate TResult Func<TResult>();
} namespace System
{
    // 摘要:
    //     Encapsulates a method that has one parameter and returns a value of the type
    //     specified by the TResult parameter.
    //
    // 参数:
    //   arg:
    //     The parameter of the method that this delegate encapsulates.
    //
    // 类型参数:
    //   T:
    //     The type of the parameter of the method that this delegate encapsulates.
    //
    //   TResult:
    //     The type of the return value of the method that this delegate encapsulates.
    //
    // 返回结果:
    //     The return value of the method that this delegate encapsulates.
    public delegate TResult Func<T, TResult>(T arg);
}

同Action类似,Func的参数从1到5个,有5个不同的重载版本
代码:


using System;
namespace ActionStudy
{
    class Program
    {
                
        static Func<string> F;
        static Func<DateTime, string> F2;               static void Main(string[] args)
        {
            F = new Func<string>(HelloWorld1);
            Console.WriteLine(F());             F2 = new Func<DateTime, string>(HelloWorld2);
            Console.WriteLine(F2(DateTime.Now));             Console.Read();         }         static string HelloWorld1()
        {
            return "Hello World!";
        }         static string HelloWorld2(DateTime time)
        {
            return string.Format("Hello World,the time is {0}.", time);
        }
       
    }   
}

五、匿名委托

ok,如果你没有晕的话,再来看一下匿名委托,其实这也是一种偷懒的小伎俩而已
看代码说话:

//F = new Func<string>(HelloWorld1);

其实也可以简写成这样:

F = HelloWorld1;

//F2 = new Func<DateTime, string>(HelloWorld2);

其实也可以简写成这样

F2 = HelloWorld2;

方法直接赋值给委托,这二个类型不同吧???

没错,你会发现编译一样能通过,系统在编译时在背后自动帮我们加上了类似 “= new Func<...>”的东东,所以我们能偷懒一下下,这个就是匿名委托。

如果你细心的话,会发现我们在定义Button的Click处理事件时,通常是这样的:

this.button1.Click += new EventHandler(button1_Click);

但有时候我们也可以写成这样:

this.button1.Click += button1_Click;

这其实就是匿名委托的应用.

六、事件event

其实,这...还是个托儿!

我们来看下按钮Click事件的定义

// 摘要:
//     Occurs when the control is clicked.
public event EventHandler Click;

继续刨根问底,查看EventHandler的定义:


using System.Runtime.InteropServices;

namespace System
{
    // 摘要:
    //     Represents the method that will handle an event that has no event data.
    //
    // 参数:
    //   sender:
    //     The source of the event.
    //
    //   e:
    //     An System.EventArgs that contains no event data.
    [Serializable]
    [ComVisible(true)]
    public delegate void EventHandler(object sender, EventArgs e);
}

看到了吧,就是委托!

Delegate,Action,Func,匿名方法,匿名委托,事件的更多相关文章

  1. Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)

    Delegate,Action,Func,匿名方法,匿名委托,事件 (转载) 一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本 ...

  2. C#-委托 lambda 匿名方法 匿名类型

    1.lambda 匿名方法 匿名类型 delegate void d1(); d1 d = delegate(){Console.WriteLine("this is a test" ...

  3. (C#) Action, Func, Predicate 等泛型委托

    (转载网络文章) (1). delegate delegate我们常用到的一种声明   Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型.   例:public del ...

  4. 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】

    1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...

  5. C# 委托应用总结(委托,Delegate,Action,Func,predicate)

    C# 委托应用总结 一.什么是委托 1.1官方解释 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法. 1.2个人理解 委托就是执 ...

  6. 委托delegate,Action,Func,Predicate

    C#委托的介绍(delegate.Action.Func.predicate) 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 ...

  7. Delegate,Action,Func,Predicate的使用与区别

    C#4.0推出后,类似Linq,Lamda表达式等许多新的程序写法层次不穷.与之相关的Delegate,Action,Func,Predicate的使用和区别也常常让大家迷惑,此处就结合实际的应用,对 ...

  8. c# action<> func<> 这2个委托怎么用和理解

    其实很好理解的呢!~首先你需要明白,他们是委托的简写形式. 一.[action<>]指定那些只有输入参数,没有返回值的委托 1.1定义一个委托: 比如,我们原来写委托: public de ...

  9. 温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件

    Tks: http://www.cnblogs.com/yjmyzz/archive/2009/11/23/1608818.html 20150801 add: http://www.cnblogs. ...

随机推荐

  1. 变长编码表 ASCII代码等长编码

    小结: 1.ASCII编码.GBK编码不是变长编码: 2.数据压缩: 示例: aabacdab → 00100110111010 → |0|0|10|0|110|111|0|10| → aabacda ...

  2. Android+Tomcat通过http获取本机服务器资源

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  3. [tcpreplay] tcpreplay高级用法--使用tcpreplay-edit进行循环动态发包

    tcpreplay-edit提供了可对包进行修改的高级用法: --unique-ip Modify IP addresses each loop iteration to generate uniqu ...

  4. day2_抓包-抓包工具Charles

    1.Charles功能简单描述 1)定位问题,前端的.后端的问题 2)发出去的请求,请求头.请求体,返回的数据 3)拦截请求,修改请求 2.Charles抓包(Android手机) 1.要求手机得和你 ...

  5. Java+selenium 如何定位下拉框select

    场景:需要进行下拉选择定位元素.   一.select菜单       select也是比较常见的,selenium封装了以下方法, 创建select WebElement selector = dr ...

  6. 浏览器数据库 IndexedDB 入门教程

    一.概述 随着浏览器的功能不断增强,越来越多的网站开始考虑,将大量数据储存在客户端,这样可以减少从服务器获取数据,直接从本地获取数据. 现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的 ...

  7. 洛谷P4562 [JXOI2018]游戏 数论

    正解:数论 解题报告: 传送门! 首先考虑怎么样的数可能出现在t(i)那个位置上?显然是[l,r]中所有无法被表示出来的数(就约数不在[l,r]内的数嘛QwQ 所以可以先把这些数筛出来 具体怎么筛的话 ...

  8. 7-通用GPIO

    7-通用GPIO 1.I/O 端口控制寄存器 每个 GPIO 有 4 个 32 位存储器映射的控制寄存器(GPIOx_MODER.GPIOx_OTYPER.GPIOx_OSPEEDR.GPIOx_PU ...

  9. Verilog如何从外部更改模块内参数

    例如有一个模块 module x(a,b,c); input a,b; output c; 'd0, h=9'd3; ...... endmodule 两种解决方法: 1.使用带有参数值的模块实例语句 ...

  10. C++中为何大量使用类指针

    C++的精髓之一就是多态性,只有指针或者引用可以达到多态.对象不行类指针的优点: 第一实现多态. 第二,在函数调用,传指针参数.不管你的对象或结构参数多么庞大,你用指针,传过去的就是4个字节.如果用对 ...