`
tudusi
  • 浏览: 1085438 次
文章分类
社区版块
存档分类
最新评论

Delegate,Action,Func,匿名方法,匿名委托,事件

 
阅读更多

一、委托Delegate

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


publicvoidHelloWorld()
{
Console.WriteLine(
"HelloWorld!");
}
publicvoidHelloWorld(stringname)
{
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),就是这种设计保证了统一的格式,不管你实际开发中想如何处理点击后的逻辑,只要按这个统一的签名来就行了
完整代码演示:


usingSystem;
namespaceActionStudy
{
classProgram
{

delegatevoidD1();
delegatevoidD2(stringmyName);


staticvoidMain(string[]args)
{
D1d1
=newD1(HelloWorld1);
d1();

D2d2
=newD2(HelloWorld2);
d2(
"Jimmy");

d2
=newD2(HelloWorld3);
d2(
"杨俊明");

Console.Read();

}

staticvoidHelloWorld1()
{
Console.WriteLine(
"HelloWorld!");
}


staticvoidHelloWorld2(stringname)
{
Console.WriteLine(
"Hello,{0}!",name);
}

staticvoidHelloWorld3(stringname)
{
Console.WriteLine(
"你好,{0}!",name);
}
}
}

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

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


usingSystem;
namespaceActionStudy
{
classProgram
{

delegatevoidD1();
delegatevoidD2(stringmyName);


staticvoidMain(string[]args)
{
D1d1
=delegate
{
Console.WriteLine(
"HelloWorld!");
};
d1();

D2d2
=delegate(stringname)
{
Console.WriteLine(
"Hello,{0}!",name);
};

d2(
"Jimmy");


d2
=delegate(stringname)
{
Console.WriteLine(
"你好,{0}!",name);
};

d2(
"杨俊明");

Console.Read();

}
}
}

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

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


usingSystem;
namespaceActionStudy
{
classProgram
{

delegatevoidD1();
delegatevoidD2(stringmyName);


staticvoidMain(string[]args)
{

D1d1
=()=>{Console.WriteLine("HelloWorld!");};
d1();

D2d2
=(stringname)=>{Console.WriteLine("Hello,{0}!",name);};
d2(
"Jimmy");

d2
=(stringname)=>{Console.WriteLine("你好,{0}!",name);};
d2(
"杨俊明");

Console.Read();

}
}
}

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

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


namespaceSystem
{
//摘要:
//Encapsulatesamethodthattakesnoparametersanddoesnotreturnavalue.
publicdelegatevoidAction();
}

namespaceSystem
{
//摘要:
//Encapsulatesamethodthattakesasingleparameteranddoesnotreturna
//value.
//
//参数:
//obj:
//Theparameterofthemethodthatthisdelegateencapsulates.
//
//类型参数:
//T:
//Thetypeoftheparameterofthemethodthatthisdelegateencapsulates.
publicdelegatevoidAction<T>(Tobj);
}

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

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


usingSystem;
namespaceActionStudy
{
classProgram
{

staticActionA1;
staticAction<string>A2;



staticvoidMain(string[]args)
{
A1
=newAction(HelloWorld1);
A1();

A2
=newAction<string>(HelloWorld2);
A2(
"Jimmy");

A2
=(stringname)=>{Console.WriteLine("你好,{0}!",name);};
A2(
"杨俊明");

A2
=delegate(stringname){Console.WriteLine("我就是委托,{0}你说对吗?",name);};
A2(
"菩提树下的杨过");

Console.Read();

}


staticvoidHelloWorld1()
{
Console.WriteLine(
"HelloWorld!");
}


staticvoidHelloWorld2(stringname)
{
Console.WriteLine(
"Hello,{0}!",name);
}


}



}

四、Func

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


namespaceSystem
{
//摘要:
//Encapsulatesamethodthathasnoparametersandreturnsavalueofthetype
//specifiedbytheTResultparameter.
//
//类型参数:
//TResult:
//Thetypeofthereturnvalueofthemethodthatthisdelegateencapsulates.
//
//返回结果:
//Thereturnvalueofthemethodthatthisdelegateencapsulates.
publicdelegateTResultFunc<TResult>();
}

namespaceSystem
{
//摘要:
//Encapsulatesamethodthathasoneparameterandreturnsavalueofthetype
//specifiedbytheTResultparameter.
//
//参数:
//arg:
//Theparameterofthemethodthatthisdelegateencapsulates.
//
//类型参数:
//T:
//Thetypeoftheparameterofthemethodthatthisdelegateencapsulates.
//
//TResult:
//Thetypeofthereturnvalueofthemethodthatthisdelegateencapsulates.
//
//返回结果:
//Thereturnvalueofthemethodthatthisdelegateencapsulates.
publicdelegateTResultFunc<T,TResult>(Targ);
}

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


usingSystem;
namespaceActionStudy
{
classProgram
{

staticFunc<string>F;
staticFunc<DateTime,string>F2;


staticvoidMain(string[]args)
{
F
=newFunc<string>(HelloWorld1);
Console.WriteLine(F());

F2
=newFunc<DateTime,string>(HelloWorld2);
Console.WriteLine(F2(DateTime.Now));

Console.Read();

}


staticstringHelloWorld1()
{
return"HelloWorld!";
}


staticstringHelloWorld2(DateTimetime)
{
returnstring.Format("HelloWorld,thetimeis{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事件的定义

//摘要:
//Occurswhenthecontrolisclicked.
publiceventEventHandlerClick;

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


usingSystem.Runtime.InteropServices;

namespaceSystem
{
//摘要:
//Representsthemethodthatwillhandleaneventthathasnoeventdata.
//
//参数:
//sender:
//Thesourceoftheevent.
//
//e:
//AnSystem.EventArgsthatcontainsnoeventdata.
[Serializable]
[ComVisible(
true)]
publicdelegatevoidEventHandler(objectsender,EventArgse);
}

分享到:
评论

相关推荐

    CSharp_Delegate C#委托

    .NET框架提供了预定义的委托类型`Action`和`Func`,它们简化了创建委托实例的过程。`Action`用于无返回值的方法,`Func`则根据参数数量和返回值类型有多种重载。 ```csharp Action&lt;string&gt; printAction = Console....

    c#中关于委托delegate的经典的实例

    C#的`async/await`关键字与委托密切相关,特别是`Func, TResult&gt;`和`Action&lt;T&gt;`等预定义委托类型。它们可以与`Task`一起用于异步操作,使代码更易读且可维护。 通过以上介绍,我们可以看到C#中的委托是一个强大且...

    delegate.zip

    自C# 2.0起,可以创建泛型委托,如`Func, TResult&gt;`和`Action, T2,...&gt;`。这些预定义的委托类型简化了代码,并提供了类型安全。 10. **委托的内存管理**: 由于委托实例可以持有对方法的引用,因此可能导致对象的...

    深入c# Func委托的详解

    在C#编程语言中,`Func`委托是一个非常重要的概念,它允许我们传递方法作为参数,从而实现函数式编程的特性。本篇文章将深入探讨`Func`委托的使用、定义和其在C#中的作用。 首先,让我们了解什么是委托。在C#中,...

    C#匿名方法与Delegate类型转换错误分析

    通过使用适当的委托类型,如`Action`、`Func`系列,或者定义扩展方法,我们可以顺利地将匿名方法传递给需要Delegate参数的方法。理解和掌握这些技巧,可以提高代码的可读性和维护性,尤其在处理事件处理和异步调用时...

    看了这个,你对事件和委托就应该理解的差不多了

    委托类型是由系统定义的`System.Delegate`类及其派生类,如`System.Action`和`System.Func`,或者你可以自定义委托类型来匹配特定的方法签名。 1. **创建和使用自定义委托**:你可以使用`delegate`关键字定义一个新...

    C#委托事件.zip

    委托类型是系统预定义的,比如`Action`、`Func`系列,也可以自定义。创建委托的关键在于定义一个委托类型,然后实例化这个类型并绑定到某个方法上。 ```csharp public delegate void MyDelegate(string message); /...

    委托的使用方法

    `Task`和`Action`、`Func`等预定义委托类型在异步编程中扮演重要角色。例如,你可以使用`Task.Run`方法启动一个新的线程来执行耗时操作,其中`Run`方法的参数就是委托。 8. **事件处理** .NET事件系统是基于委托的...

    C#委托 C#委托 C#委托

    在C#编程语言中,委托(Delegate)是一种强大的特性,它允许我们把方法作为参数传递,或者存储在变量中,从而实现回调函数和事件处理。本文将深入探讨C#委托的概念、用途、类型以及如何使用`DynamicInvoke`方法。 #...

    事件与委托

    Lambda表达式和匿名委托在处理事件时特别有用,因为它们允许我们在订阅事件时避免创建额外的命名方法。这不仅简化了代码,还减少了内存占用,因为匿名方法不需要独立的委托实例。 在实际开发中,结合使用事件和...

    委托传方法案例委托传方法案例

    委托类型是预定义的(如`Action`和`Func`)或自定义的,自定义委托需要通过`delegate`关键字来创建。 2. **声明委托** 要创建一个自定义委托,你需要定义一个新类型,指定它的返回类型和参数列表。例如: ```...

    C_threads_events_delegate_instance.rar_delegate_threads_线程委托

    例如,`System.Action`和`System.Func`是一组内置的委托类型,分别用于无返回值和有返回值的方法。 结合线程和委托,可以实现异步编程,使得代码能够在不同的线程上执行。例如,`ThreadPool`类提供了一种灵活的方式...

    .NET委托解析

    例如,`Action&lt;T&gt;`和`Func, R&gt;`是一组常用的预定义泛型委托。 【六】委托的进步:语法糖、匿名方法和闭包 C#引入了匿名方法和Lambda表达式,使委托的使用更为简洁。这些语法糖使得我们可以直接在声明委托实例时...

    delegate正、逆传值

    在编程领域,委托(Delegate)是C#等.NET框架中的一个重要概念,它允许我们传递方法作为参数,实现回调机制或事件处理。在这个“delegate正、逆传值”的实践中,我们将深入探讨委托如何在方法间传递数据,以及如何...

    delegate学习

    在异步编程中,`Delegate`与`Task`、`Action`、`Func`等一起工作,实现非阻塞操作。`async`关键字配合`await`可以与`Delegate`无缝集成,提供更高效的异步执行流程。 七、Delegate的类型安全 由于`Delegate`是基于...

    委托与事件

    委托类型是由系统定义的(如`Action`和`Func`系列)或由用户自定义。 #### 定义委托 定义一个委托类型的语法如下: ```csharp public delegate return_type delegate_name(parameters); ``` 例如,定义一个返回整数...

    C# 委托源码

    普通委托是C#中的预定义类型,如`System.Action`或`System.Func`,它们代表了具有特定签名的方法。创建自定义委托类型,我们需要定义一个类,继承自`System.Delegate`,并声明其方法签名。例如: ```csharp ...

    C#委托方法的学习教源码(特别适合新手)

    - C# 4.0引入了`Task`和`Action&lt;T&gt;`、`Func&lt;T&gt;`等委托类型,简化了异步编程。`async`和`await`关键字结合委托可以编写出简洁的异步代码。 9. **线程安全** - 调用多播委托时需要注意线程安全问题,特别是在多线程...

    多播委托,并解决多播委托出现异常,不能迭代

    - 利用`Action&lt;T&gt;`或`Func&lt;T&gt;`等泛型委托,它们支持匿名方法和Lambda表达式,可以方便地添加异常处理。 4. **迭代调用**:另一种策略是使用循环和迭代来逐一调用多播委托中的方法,这样每个方法都在独立的上下文中...

    委托 实例窗体互动 C#

    在C#编程中,委托是实现事件处理和回调机制的关键工具。...在实际开发中,结合.NET框架提供的各种委托类型,如`Action`和`Func`,以及现代C#特性,如Lambda表达式和异步编程,能够极大地提升开发效率和代码质量。

Global site tag (gtag.js) - Google Analytics