2012年5月24日 星期四

LINQ 學習筆記 (pre.1) 擴充方法 - Extension Methods

LINQ ( Language-Integrated Query ) 是微軟在 C# 3.0 以及 VB9 之後發展的一套查詢技術,目的在試圖打破資料存取方式 (不是單指資料庫) 與程式溝通的界線。

以往程式需使用資料的時候,例如 SQL SERVER ,便需要利用到 T-SQL 語法,建立 Connection,搭配 Command 來進行資料的存取。中間需要將欲處理資料轉由 Command Text ,搭配  Parameters 以便控制資料庫。

而為什麼說不單指資料庫,因為 XML、EXCEL 等存取媒介也能由 LINQ 來進行資料的控制,這也是微軟想發展 LINQ 的原因之一。

而要發展 LINQ 也因此需要付出一些建置成本,也就是因應需應該有一些環境特性。所以引用In 91的文章。概念如下:

  1. var (隱含型別)
  2. 匿名型別
  3. 擴充方法
  4. yield、Iterator、IEnumerable、IEnumerator
  5. Enumerable與IEnumerable<T>
  6. Fluent Interface
  7. lambda (匿名方法)
  8. 一些特殊的委派型別 (Func<T>, Action<T>, Predicate<T>)
  9. 從foreach了解LINQ
  10. 延遲執行的特性




其中擴充方法,根據 MSDN 文件,一開始會被太過專業的文字說明所困,所以一開始便直接引述程式碼來說明會比較容易快速進入狀況一點。
 static void test()
    {
        int[] ints = { 10, 45, 15, 39, 21, 26 };
        //OrderBy這個方法便是擴充方法
        var result = ints.OrderBy(g => g);
        foreach (var i in result)
        {
            System.Console.Write(i + " ");
        }
    }


我們在宣告上面,是用 int 的陣列去宣告使用,但是如果開始使用到 LINQ 是使用 var (隱含型別) 去使用的,這時候就會發生,那原本宣告的型別怎麼辦?微軟便是利用擴充方法,來處理這類似的狀況。利用另外撰寫方法來處理成 LINQ 可以利用的型別,這就是稱作擴充方法的由來。而這方法也並不是只針對 LINQ 才能使用,其他有需用到這樣的方法也可以進行使用。

以上範例是建立在 int 陣列宣告的內建擴充方法,接下來自行撰寫擴充方法。
注意事項大概有以下幾個。
  1. 寫擴充方法的地方需要 using 原類別所在的 namespace。
  2. 第一個參數需要用 this 前置詞,引導原類別引入,而方法如有參數,則放置第二個位置之後。
  3. 雖然有靜態宣告的前置詞 static ,所以擴充方法是定義為靜態方法,但使用執行個體方法語法進行呼叫,也就是需要事先宣告或是命名。
而這樣寫或許有些問號,直接看程式碼會比較容易點。

1.先撰寫一個很基礎的原程式類別,然後暫時放在一個名為 DefineDemo 的命名空間,以便保持一個獨立的空間。而程式的意思是我皮夾只有100塊...囧
namespace DefineDemo
{
    public class myWallet
    {
        public myWallet()
        {

        }

        public static int Cash()
        {
            return 100;
        }

    }
}


2.現在要撰寫一個擴充方法啦,類別名字
我把它放在 Deafult.aspx.cs 裡面,所以我在上方 using DefineDemo ,以便準備載入原類別 myWallet。
/// <summary>
/// 自行定義一個類別名稱,預備載入原類別進行擴充方法
/// </summary>
public static class MyExtensions
{
    //擴充方法需要引用兩個前置詞 static 跟 this 。而後面是如果需要載入參數再使用。
    public static int iCash(this myWallet objWallet, int Cash)
    {
        return Cash;
    }
}


3.然後我在原來 Page_Load 的位置,來使用擴充方法。
public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //擴充方法是沒有辦法直接使用靜態方法的
        //也就是並沒有辦法向下列靜態使用方法那樣直接使用myWallet.iCash(145);
        int myCash = myWallet.Cash();
        //需要事先宣告或命名
        myWallet objmyWallet = new myWallet();
        int myiCash = objmyWallet.iCash(145);
    }
}



再次整理出:
  1. 不動到原本程式類別,就可以擴充方法。
  2. 是需要執行個體成能使用的靜態方法。
而為什麼要說這個,因為很多原本的陣列或是 DataSet 都是比 LINQ 早發展。而為什麼 LINQ 可以不動到原本的 類別定義程式碼 就可以直接用語法來進行查詢,這便是利用到擴充方法的忙,來擴充實作 Enumerable 或 IEnumerable<T> 介面,快速將 LINQ 這套技術導入嚕。

[.NET]快快樂樂學LINQ系列-前言
HOW TO:實作和呼叫自訂擴充方法 (C# 程式設計手冊)

沒有留言:

張貼留言