利用委派讓List(T)可以使用Lambda運算式寫法

在網路上看到越來越的開源程式碼範例,拐彎抹角的使用了一大堆委派的寫法來展現出自己高超過人的程式設計技巧,從來沒想過會有人把委派塞入到System.Collections.Generic.List<T>再跑迴圈讓這個集合運作起來,初次遇見算是增長見識了。

傳統delegate簽名的寫法

這個寫法巧妙的利用泛型的機制,將delegate myWork()塞入到System.Collections.Generic.List<T>,這麼一來就可以在List.Add()時期快樂的使用黏巴達(Lambda)來寫程式了。

class Program
{
  public delegate void myWork();
  public static void Main()
  {
    System.Collections.Generic.List<myWork> oList = new System.Collections.Generic.List<myWork>();

    //此處不可使用 For-Next 迴圈,不然會引爆C#閉包(Closure)區域參數問題
    foreach (var i in new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })
    { //將自建函式封裝進去
      oList.Add(() =>
      {
        for (int j = 1; j < 10; j++)
        {
          Console.WriteLine($"{i} X {j} = {i * j}");
        }
      });
    }

    foreach (var oItem in oList)
    { //全部叫出來執行
      oItem();
    }

    Read();
  }
}

使用System.Action或System.Func的寫法

這種寫法算是C#後期大家都採用的寫法,可以省略掉delegate簽名的宣告(程式設計師可以少想一個變數名稱),由於這次的DEMO是99乘法表,並沒有任何的傳入傳出值,因此採用System.Action<T>來示範即可。

class Program
{
  public static void Main()
  {
    System.Collections.Generic.List<System.Action> oList = new System.Collections.Generic.List<Action>();

    //此處不可使用 For-Next 迴圈,不然會引爆C#閉包(Closure)區域參數問題
    foreach (var iItem in new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })
    { //將自建函式封裝進去
      oList.Add(() => {
        for (int i = 0; i < 10; i++)
        {
          Console.WriteLine($"{iItem} X {i} = {iItem * i}");
        }
      });
    }

    foreach (var oItem in oList)
    { //全部叫出來執行
      oItem();
    }

    Read();
  }
}

補充:改用更精簡的事件疊加掛載寫法

public class Program
{
  public static void Main()
  {
    System.Action fAction = null;
    //此處不可使用 For-Next 迴圈,不然會引爆C#閉包(Closure)區域參數問題
    foreach (var iItem in new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })
    { //將自建函式封裝進去
      fAction += new Action(() => {
        for (int i = 0; i < 10; i++)
        {
          Console.WriteLine($"{iItem} X {i} = {iItem * i}");
        }
      });
    }
    //叫出來執行10個匿名函式
    fAction();
  }
}

目前職業生涯中還沒有遇過這樣的寫法適用的情境,先備份起來日後若有用途可以拿出來參考。另外有關於「引爆C#閉包(Closure)區域參數問題」可參考匿名函式陷阱

相關連結:

System.Collections.Generic.List List(T) Delegate Lambada