初识c#委托,delegate,Func,Action
来源:互联网 发布:大学社团网络部职能 编辑:程序博客网 时间:2024/05/29 10:45
委托的使用
法庭上律师为当事人辩护,他真正执行的是当事人的陈词,律师就相当于一个委托对象,而当事人则委托律师对象为自己辩护。
C#中的委托概念也就好比律师对象,它是一个类,委托是类类型,因为只有类才有对象的概念。
C#中的委托可以理解为函数的一个包装,它使得C#中的函数可以作为参数来传递,这在作用上相当于C++的函数指针。C++用户函数指针获取函数的入口地址,然后通过这个指针来实现对函数的操作。
委托的定义和方法的定义类似,只是在定义的前面多了一个delegate关键字,可以被委托包装的方法必须满足以下原则:
- 方法的签名必须与委托一致,方法签名包括参数的个数、类型和顺序;
- 方法的返回类型要和委托一致,注意,方法的返回类型不属于方法签名的一部分。
例子:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DelegateUse{ // 委托使用演示 class Program { // 1. 使用delegate关键字来定义一个委托类型 delegate void MyDelegate(int para1, int para2); static void Main(string[] args) { // 2. 声明委托变量d MyDelegate d; // 3. 实例化委托类型,传递的方法也可以为静态方法,这里传递的是实例方法 d = new MyDelegate(new Program().Add); // 4. 委托类型作为参数传递给另一个方法 MyMethod(d); Console.Read(); } // 该方法的定义必须与委托定义相同,即返回类型为void, 两个int类型的参数 void Add(int para1, int para2) { int sum = para1 + para2; Console.WriteLine("两个数的和为:"+sum); } // 方法的参数是委托类型 private static void MyMethod(MyDelegate mydelegate) { // 5.在方法中调用委托 mydelegate(1,2); } }}
使用委托的步骤:定义委托类型->声明委托变量->实例化委托->作为参数传递给方法->调用委托。
- 定义委托类型:
delegate void MyDelegate(int para1, int para2)
;其定义方式类似于方法的定义,只是多了一个delegate关键字。 - 声明委托变量:
MyDelegate d
;既然委托是一种类型,那么可以使用委托来声明一个委托变量,相当于int a
。 - 实例化委托:
d = new MyDelegate(new Program().Add)
;第二步只是声明了委托变量,但并没有将它实例化。类的实例化使用new关键字实现,而委托也属于类类型,所以委托的实例化也使用new关键字来进行的。这里需要注意的是,委托的实例化是用一个方法名(不能带左右括号)作为参数,并且该方法的定义必须符合委托的定义,即该方法的返回类型。参数个数和类型必须与委托定义中的一样。 - 作为参数传递给方法:
MyMethod(d)
;委托使得在C#中,可以把一个方法作为另一个方法的参数,而委托可以看做是一个包装方法的对象。 - 在方法中调用委托。MyMethod方法好比是法官,MyMethod方法调用委托,委托再调用方法InstanceMethod。
为什么要引入委托
引入委托之后,就可以把函数作为参数传递给另外一个方法,提高方法的扩展性。
例子:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DelegateOrigin{ class Program { static void Main(string[] args) { // 引入委托之后 // 初始化对象 Program p = new Program(); p.Greeting("李志", p.ChineseGreeting); p.Greeting("Tommy Li", p.EnglishGreeting); Console.Read(); } #region 引入委托之后 // 定义委托类型 public delegate void GreetingDelegate(string name); // 有了委托之后,可以像如下实现打招呼方法 public void Greeting(string name, GreetingDelegate callback) { // 调用委托 callback(name); } // 英国人打招呼方法 public void EnglishGreeting(string name) { Console.WriteLine("Hello, " + name); } // 中国人打招呼方法 public void ChineseGreeting(string name) { Console.WriteLine("你好, " + name); } public void JapaneseGreeting(string name) { Console.WriteLine("こんにちは, "+name); } #endregion #region 没有委托的情况 //// 不使用委托实现打招呼方法 //public void Greeting(string name,string language) //{ // switch (language) // { // case "zh-cn": // ChineseGreeting(name); // break; // case "en-us": // EnglishGreeting(name); // break; // default: // EnglishGreeting(name); // break; // } //} //// 英国人打招呼方法 //public void EnglishGreeting(string name) //{ // Console.WriteLine("Hello, "+name); //} //// 中国人打招呼方法 //public void ChineseGreeting(string name) //{ // Console.WriteLine("你好, "+name); //} #endregion } }
委托链
委托封装一个方法的情况,可理解为一个律师只为一个当事人辩护。但律师为多个当事人辩护的情况是存在的,C#中委托也同样可以封装多个方法。C#中把封装多个方法的委托称作委托链或多路广播委托。
可以使用 +运算符把委托链接到一个委托对象实例上,也可以用-运算符将某个委托从委托链对象上移除。
例子:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace MulticastDelegates{ class Program { // 声明一个委托类型 public delegate void DelegateTest(); static void Main(string[] args) { // 用静态方法来实例化委托 DelegateTest dtstatic = new DelegateTest(Program.method1); DelegateTest dtinstance= new DelegateTest(new Program().method2); // 定义一个委托对象,一开始初始化为null,就是不代表任何方法(我就是我,我不代表任何人) DelegateTest delegatechain = null; // 使用+符号链接委托,链接多个委托后就成为委托链了 delegatechain += dtstatic; delegatechain += dtinstance; // 使用-运算符把dtstatic委托从委托链中移除 delegatechain -= dtstatic; // 调用委托链 delegatechain(); Console.Read(); } // 静态方法 private static void method1() { Console.WriteLine( "这是静态方法"); } // 实例方法 private void method2() { Console.WriteLine( "这是实例方法"); } }}
Func委托
Func<T, TResult> 委托封装一个方法,该方法具有一个参数,且返回由 TResult 参数指定的类型的值。使用 Func<T, TResult> 委托时,您无需显式定义一个封装具有单个参数的方法的委托。
例如,下面的代码显式声明的委托名为 ConvertMethod 和分配的引用 UppercaseString 给其委托实例的方法。
using System;delegate string ConvertMethod(string inString);public class DelegateExample{ public static void Main() { // Instantiate delegate to reference UppercaseString method ConvertMethod convertMeth = UppercaseString; string name = "Dakota"; // Use delegate instance to call UppercaseString method Console.WriteLine(convertMeth(name)); } private static string UppercaseString(string inputString) { return inputString.ToUpper(); }}
下面的示例简化了此代码实例化 Func
using System;public class GenericFunc{ public static void Main() { // Instantiate delegate to reference UppercaseString method Func<string, string> convertMethod = UppercaseString; string name = "Dakota"; // Use delegate instance to call UppercaseString method Console.WriteLine(convertMethod(name)); } private static string UppercaseString(string inputString) { return inputString.ToUpper(); }}
还可以使用 Func
using System;public class Anonymous{ public static void Main() { Func<string, string> convert = delegate(string s) { return s.ToUpper();}; string name = "Dakota"; Console.WriteLine(convert(name)); }}
还可以分配到的 lambda 表达式 Func
using System;public class LambdaExpression{ public static void Main() { Func<string, string> convert = s => s.ToUpper(); string name = "Dakota"; Console.WriteLine(convert(name)); }}
下面的示例演示如何声明和使用 Func
using System;using System.Collections;using System.Collections.Generic;using System.Linq;static class Func{ static void Main(string[] args) { // Declare a Func variable and assign a lambda expression to the // variable. The method takes a string and converts it to uppercase. Func<string, string> selector = str => str.ToUpper(); // Create an array of strings. string[] words = { "orange", "apple", "Article", "elephant" }; // Query the array and select strings according to the selector method. IEnumerable<String> aWords = words.Select(selector); // Output the results to the console. foreach (String word in aWords) Console.WriteLine(word); }}
Action委托
Action<T> 委托封装一个方法,该方法只有一个参数并且不返回值。使用方法与Func大致相同。
using System;using System.Windows.Forms;public class TestAction1{ public static void Main() { Action<string> messageTarget; if (Environment.GetCommandLineArgs().Length > 1) messageTarget = ShowWindowsMessage; else messageTarget = Console.WriteLine; messageTarget("Hello, World!"); } private static void ShowWindowsMessage(string message) { MessageBox.Show(message); }}
参考资料:
- 《Learning hard C#学习笔记》
- https://msdn.microsoft.com/zh-cn/library/bb549151(v=vs.110).aspx
- https://msdn.microsoft.com/zh-cn/library/018hxwa8(v=vs.110).aspx#中国 (简体中文)
0 0
- 初识c#委托,delegate,Func,Action
- C# 委托(Delegate Action Func Predicate)
- .net Delegate ,Func ,Action 委托
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C# 四种委托 Delegate Action Func Predicate 的学习
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- C#委托的介绍(delegate、Action、Func、predicate)
- mysql存储引擎InnoDB-MyISAM
- hdu1283
- C语言的返回值return总结
- 4-2 Shortest Path [4]
- 数字图像处理之空间域滤波和锐化(Octave实现)
- 初识c#委托,delegate,Func,Action
- 描述文件状态失效(profile invalid)
- golang 新手练习 go语言 10分钟练习贴
- [Java]_[线程同步]
- 用配置文件字段区分外网机器和测试机器!
- 反常积分计算细节
- 如何搭建maven的聚合工厂并运行
- 使控件可拖拽
- 关于struts2.5XWork校验框架的问题