利用yield return與IEnumerable(T)來讓ORM類別可以被集合化與尋訪

一般來說,如果我在進行ORM(Object Relational Mapping)類別的輸出,丟到外部要另外進行處理時,我都會調用System.Collections.Generic.List來進行處理。但是List畢竟已經時做過完整的IEnumerable程式碼了,在效能上可能會耗損過多的系統資源,因此我們可以改用IEnumerable來進行處理,對於單純運送物件集合包上面的動作,對記憶體的耗損上可能會有比較高的系統效率。

IEnumerable的使用方式

IEnumerable顧名思義就是一個泛型的介面,用來當作一個集合容器,我們從下方的程式碼中可以發現,當你實作這個泛型介面時,可以將任何的實體塞進去。以下面為例,這是字串陣列IEnumerable化的使用方式。有了IEnumerable化後,我們就可以使用最喜歡的foreach來尋訪它。

static void Main(string[] args)
{
  IEnumerable<string> oTemp = new string[] { "小明", "小華", "小英", "老王" };
  foreach (string obj in oTemp)
  {
    Console.WriteLine(obj);
  }
  Console.WriteLine("--- END ---");
  Console.Read();
}

當然,要塞自訂的物件實體也沒問題。

class emp
{
  public string cName {get; set;}
}
static void Main(string[] args)
{
  IEnumerable<emp> oTemp = new emp[] {
    new emp { cName = "小明" },
    new emp { cName = "小華" },
  };
  foreach (emp obj in oTemp)
  {
    Console.WriteLine(obj.cName);
  }
  Console.WriteLine("--- END ---");
  Console.Read();
}

接下來換yield return出場

現在問題來了,假設你從資料庫讀到了一千筆資料放在DataTable中,我們應該不會想要慢慢new到字串陣列再使其自動轉換成IEnumerable,而這也不是List可以讓我們來Add(Object),這時候我們可以請神(yield return)上身嘍!yield return會幫我們把要輸出的物件一個轉成IEnumerable,並且動態的丟出去。

class Program
{
  static void Main(string[] args)
  {
    foreach (ORMEmployee obj in GetList.Employee())
    {
      Console.WriteLine(obj.cName);
    }
    Console.WriteLine("--- END ---");
    Console.Read();
  }
}
class ORMEmployee
{
  public string cName { get; set; }
}

class GetList
{
  public static IEnumerable<ORMEmployee> Employee()
  {
    //這裡可能取材自資料庫之類的東西
    string[] aryEmployee = new string[] { "小明", "小華", "小英", "老王" };
    foreach (string cTemp in aryEmployee)
    {
      yield return new ORMEmployee() { cName = cTemp };
    }
  }
}

當然啦,沒有List的缺點就是你沒有辦法進行後續的Add()、Remove()等操作,這是大家可能要先有心理準備的事。此外,IEnumerable依然是可以被強大的Json.Net序列化的喔!詳見下列程式碼:

Console.WriteLine(
  Newtonsoft.Json.JsonConvert.SerializeObject(GetList.Employee())
);
System.Collections.IEnumerable(T) System.Collections.Generic(T) YieldReturn YieldBreak