public delegate void Action()
Action<T>:Action的泛型实现了1到16个传入参数的定义,但是仍然没有返回值,得出结论Action不支持返回值,如果需要返回值请使用另一个系统委托Func
public delegate void Action<in T>(T obj) ... public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>( T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16 )
由此可见Action的定义非常简单,但是这样的委托实在是太常用了,如果用一次自己定义一个也是可以的,多的话就感觉重复劳动太多:
过去自定义委托:
using System; using System.Windows.Forms; public delegate void ShowValue(); public class Name { private string instanceName; public Name(string name) { this.instanceName = name; } public void DisplayToConsole() { Console.WriteLine(this.instanceName); } public void DisplayToWindow() { MessageBox.Show(this.instanceName); } } public class testTestDelegate { public static void Main() { Name testName = new Name("Koani"); ShowValue showMethod = testName.DisplayToWindow; showMethod(); } }
现在直接使用Action:
using System; using System.Windows.Forms; public class Name { private string instanceName; public Name(string name) { this.instanceName = name; } public void DisplayToConsole() { Console.WriteLine(this.instanceName); } public void DisplayToWindow() { MessageBox.Show(this.instanceName); } } public class testTestDelegate { public static void Main() { Name testName = new Name("Koani"); Action showMethod = testName.DisplayToWindow; //将 Action 委托与匿名方法一起使用 // Action showMethod = delegate() { testName.DisplayToWindow();} ; //将 lambda 表达式分配给 Action 委托实例 //Action showMethod = () => testName.DisplayToWindow(); showMethod(); } }
Action<T>的使用也是类似的,但是 Action<T>的定义是比较特别的,它有一个关键词In,In是用来干嘛的呢,按照MSDN的解释:
关于派生程度更小或更低的类型等相关的概念理解我推荐深入理解 C# 协变和逆变
Func:封装一个不具有参数但却返回 TResult 参数指定的类型值的方法
public delegate TResult Func<out TResult>()
Func<T>: Func的泛型同样的实现了1到16个传入参数,而且支持返回值。
public delegate TResult Func<in T, out TResult>( T arg ) ... public delegate void Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>( T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16 )
Func的定义同样简单明了,和Action一样是为了简化代码方便”客户“使用:
过去自定义委托:
using System; using System.IO; delegate bool WriteMethod(); public class TestDelegate { public static void Main() { OutputTarget output = new OutputTarget(); WriteMethod methodCall = output.SendToFile; if (methodCall()) Console.WriteLine("Success!"); else Console.WriteLine("File write operation failed."); } } public class OutputTarget { public bool SendToFile() { try { string fn = Path.GetTempFileName(); StreamWriter sw = new StreamWriter(fn); sw.WriteLine("Hello, World!"); sw.Close(); return true; } catch { return false; } } }
现在直接使用Func:
using System; using System.IO; public class TestDelegate { public static void Main() { OutputTarget output = new OutputTarget(); Func<bool> methodCall = output.SendToFile; //Func<bool> methodCall = delegate() { return output.SendToFile(); };将 Func<TResult> 委托与匿名方法一起使用 // Func<bool> methodCall = () => output.SendToFile(); 将 lambda 表达式分配给 Func<T, TResult> 委托 if (methodCall()) Console.WriteLine("Success!"); else Console.WriteLine("File write operation failed."); } } public class OutputTarget { public bool SendToFile() { try { string fn = Path.GetTempFileName(); StreamWriter sw = new StreamWriter(fn); sw.WriteLine("Hello, World!"); sw.Close(); return true; } catch { return false; } } }
通过定义可以看到Func的定义不仅可以看到In关键词的身影,还有一个Out关键词,MSDN的解释如下(Out作为方法的输出参数也是经常用到的):
关于派生程度更大或更高的类型等相关的概念理解我依然推荐深入理解 C# 协变和逆变