轉:https://www.cnblogs.com/wyongqi/p/7483748.html
如果我們希望定義一個委託類型來調用任何返回void並且接受單個參數的方法。如果這個參數可能會不同,我們就可以通過類型參數來構建。
下面我們看一個小示例:
public class GenericDelegate { public delegate void MyGenericDelegate<T>(T arg); public static void Show() {
// 註冊目標 MyGenericDelegate<string> stringTarget = new MyGenericDelegate<string>(StringTarget); stringTarget("i am ok"); MyGenericDelegate<int> intTarget = new MyGenericDelegate<int>(IntTarget); intTarget.Invoke(100); } static void StringTarget(string arg) => Console.WriteLine($"StringTarget--> {arg.ToUpper()}"); static void IntTarget(int arg) => Console.WriteLine($"IntTarget--> {++arg}"); }
a. 泛型Action<> 和 Func<> 委託
從以上的學習中我們已經瞭解到,使用委託在應用程序中進行回調需要遵循以下步驟:
- 自定義一個與要指向的方法格式相匹配的委託
- 創建自定義委託的實例,將方法名作爲構造函數的參數
- 通過調用委託對象的Invoke()方法來間接調用該方法
其實,這種方式通常會構建大量只用於當前任務的自定義委託。當委託名無關緊要的時候,我們可以使用框架內置的Action<> 和 Func<> 泛型委託,可指向至多傳遞16個參數的方法。
Action<>:無返回值: 定義 public delegate void Action<...>
public class MyActionDelegate { public static void Show() { // 使用Action<>委託來指向 DisplayMessage() Action<string, ConsoleColor, int> actionTarget = new Action<string, ConsoleColor, int>(DisplayMessage); actionTarget("actionTarget", ConsoleColor.Red, 5); } // Action<> 委託的一個目標 private static void DisplayMessage(string msg, ConsoleColor txtColor, int printCount) { ConsoleColor previous = Console.ForegroundColor; Console.ForegroundColor = txtColor; for (int i = 0; i < printCount; i++) { Console.WriteLine(msg); } Console.ForegroundColor = previous; } }
運行效果如下圖:
Func<>:有返回值 public delegate TResult Func<..., out TResult>
Func的 參數列表中,最後一個是返回類型,前面的都是參數類型
public class FuncDelagate { public static void Show() { Func<int, int, int> funcTarget = new Func<int, int, int>(Add); int result = funcTarget(1, 2); Console.WriteLine(result); Func<int, int, string> funcTarget2 = new Func<int, int, string>(SumToString); string sumStr = funcTarget2(3, 4); Console.WriteLine(sumStr); } static int Add(int x, int y) => x + y; static string SumToString(int x, int y) => (x + y).ToString(); }
運行結果:3,7
鑑於 Action<> 和 Func<> 節省了手工創建自定義委託的步驟,but 總是應該使用他們嗎?
答案:“視情況而定”。
很多情況下 Action<> 和 Func<> 都是首選,但如果你覺得一個具有自定義名稱的委託更有助於捕獲問題範疇,那麼構建自定義委託不過就是一行代碼的事兒。
注:Linq中就大量的用到了 Action<> 和 Func<>。