惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Help Net Security
Help Net Security
G
Google Developers Blog
雷峰网
雷峰网
WordPress大学
WordPress大学
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Engineering at Meta
Engineering at Meta
Security Latest
Security Latest
T
Threat Research - Cisco Blogs
AWS News Blog
AWS News Blog
F
Full Disclosure
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Exploit Database - CXSecurity.com
J
Java Code Geeks
U
Unit 42
C
Cyber Attacks, Cyber Crime and Cyber Security
V
V2EX
C
Cisco Blogs
博客园 - 司徒正美
Project Zero
Project Zero
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
Scott Helme
Scott Helme
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
S
Securelist
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
T
Threatpost
Recorded Future
Recorded Future
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
The Register - Security
The Register - Security
S
Security Archives - TechRepublic
博客园 - Franky
N
News | PayPal Newsroom
Simon Willison's Weblog
Simon Willison's Weblog
S
SegmentFault 最新的问题
W
WeLiveSecurity
A
Arctic Wolf
B
Blog

博客园 - xqiwei

WCF RIA Services DomainService life-cycle and adding Transactions C#多线程 使用委托更新UI实例(WP7开发 其他线程中更新UI)(转载) looping(and modifying) a collection - xqiwei LineBreak in a tooltip in xaml - xqiwei GetObjectbyKey in E.F. vs. Querying for a single entity Use GetObjectByKey() for better performance Visual Studio集成开发环境无法启动调试 C#中关于String.Equals(object,object)和(object==object )的比较 - xqiwei - 博客园 IValueConverter 接口 ASP.NET页面生命周期和asp.net应用程序生命周期 Windows Presentation Foundation Tools and Controls ArcEngine开发之Command控件使用篇 Resharper进阶 C# 中的委托和事件 WPF系列文章 - xqiwei 新技术文章 - xqiwei flash与javascript、asp.net(数据库)的交互 使用vs.net ajax实现幻灯片的效果 职业规划
Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)
xqiwei · 2012-02-16 · via 博客园 - xqiwei

一、委托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);
}

看到了吧,就是委托!

转载请注明来自菩提树下的杨过http://www.cnblogs.com/yjmyzz/archive/2009/11/23/1608818.html