天天看點

LINQ To SQL深入學習系列之二(C#3.0為LINQ的加強之二)

本文大部分内容整理自msdn

3、分部方法

分部方法使類的某個部分的實施者能夠定義方法(類似于事件)。類的另一部分的實施者可以決定是否實作該方法。如果未實作該方法,編譯器将移除方法簽名以及對該方法的所有調用。是以,分部類中的任何代碼都可以随意地使用分部方法,即使未提供實作也是如此。如果調用了未實作的方法,将不會導緻編譯時錯誤或運作時錯誤。

在自定義生成的代碼時,分部方法特别有用。這些方法允許保留方法名稱和簽名,是以生成的代碼可以調用方法,而開發人員可以決定是否實作方法。與分部類非常類似,分部方法使代碼生成器建立的代碼和開發人員建立的代碼能夠協同工作,而不會産生運作時開銷。

分部方法聲明由兩個部分組成:定義和實作。它們可以位于分部類的不同部分中,也可以位于同一部分中。

<a></a>

namespace PM

{

    partial class A

    {

        partial void OnSomethingHappened(string s);

    }

    // This part can be in a separate file.

        // Comment out this method and the program

        // will still compile.

        partial void OnSomethingHappened(String s)

        {

            Console.WriteLine("Something happened: {0}", s);

        }

}

要點:

1、分部方法聲明必須以上下文關鍵字 partial 開頭,并且方法必須傳回 void。

2、分部方法可以有 ref 參數,但不能有 out 參數。

3、分部方法為隐式 private 方法,是以不能為 virtual 方法。

4、分部方法不能為 extern 方法,因為主體的存在确定了方法是在定義還是在實作。

5、分部方法可以有 static 和 unsafe 修飾符。

6、分部方法可以為泛型的。限制将放在定義分部方法聲明上,但也可以選擇重複放在實作聲明上。參數和類型參數名稱在實作聲明和定義聲明中不必相同。

7、不能将委托轉換為分部方法。

場景舉例:輕量級事件處理

  有的時候,自動生成的代碼需要事件這類語言構造來通知使用者對某些操作進行處理,但實際上用于編寫的代碼就位于自動生成的類型之中。此時,或者需要觸發一個事件,或者就需要生成一個virtual方法來讓使用者繼承。但無論是事件還是繼承,開銷都是比較大的,是以可以通過分部方法來實作輕量級的處理方式。如下面的類:

 partial class Customer

    { 

        string name; 

        public string Name 

        { 

            get 

            { 

                return name; 

            } 

            set 

                OnBeforeUpdateName(); 

                OnUpdateName(); 

                name = value; 

                OnAfterUpdateName(); 

        } 

        partial void OnBeforeUpdateName(); 

        partial void OnAfterUpdateName(); 

        partial void OnUpdateName(); 

    } 

 這裡定義了三個分部方法,其意義不言而喻。假設這是系統自動生成的代碼,則我們隻需在另外一個源代碼檔案中的partial class Customer中實作這幾個分部方法即可。

另外在自定義DataContext中的Insert、Update、Delete方法也會用到分部類,等我們講到DataContext時再詳細講解這部分。

4、擴充方法:

擴充方法使您能夠向現有類型“添加”方法,而無需建立新的派生類型、重新編譯或以其他方式修改原始類型。擴充方法是一種特殊的靜态方法,調用擴充方法與調用在類型中實際定義的方法之間沒有明顯的差異。擴充方法是可以通過使用執行個體方法文法調用的靜态方法。效果上,使得附加的方法擴充已存在類型和構造類型成為可能。他可以對現有類功能進行擴充,進而使該類型的執行個體具有更多的方法。擴充方法有助于把今天動态語言中流行的對快速錄入支援的靈活性,與強類型語言之性能和編譯時驗證融合起來。這裡先舉一個msdn中的例子:

下面的示例示範為 System.String 類定義的一個擴充方法。假設我要分析一個字元串,希望得到字元串中單詞的個數,一般情況下我們可能使用一個統計的函數來解決這個問題

static void Main(string[] args)

            string s = "Hello Extension Methods";

            Console.WriteLine(WordCount(s));         

        static int WordCount(string str)

            return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;

但這樣用起來感覺上可能會很别扭,這個WordCount方法如果就是字元串類中的一個方法多好,像所有字元串的執行個體方法一樣用。這裡我們引出擴充方法來解決這個問題。

namespace ExtensionMethods

    public static class MyExtensions

        public static int WordCount(this String str)

    }   

注意,上面的靜态方法在第一個類型是string的參數變量前有個“this”關鍵詞,這告訴編譯器,這個特定的擴充方法應該添加到類型為“string”的對象中去。

使用 using 指令将 WordCount 擴充方法放入範圍中:

using ExtensionMethods;

string s = "Hello Extension Methods";

int i = s.WordCount();

擴充方法要點 

1、擴充方法的本質為将執行個體方法調用在編譯期改變為靜态類中的靜态方法調用。事實上,它确實擁有靜态方法所具有的所有功能。 

2、通常,您更多時候是調用擴充方法而不是實作您自己的擴充方法。由于擴充方法是使用執行個體方法文法調用的,是以不需要任何特殊知識即可從用戶端代碼中使用它們。若要為特定類型啟用擴充方法,隻需為在其中定義這些方法的命名空間添加 using 指令。

3、擴充方法的優先級:現有執行個體方法優先級最高,其次為最近的namespace下的靜态類的靜态方法,最後為較遠的namespace下的靜态類的靜态方法。(與接口或類方法具有相同名稱和簽名的擴充方法永遠不會被調用 )

4、在代碼中,可以使用執行個體方法文法調用該擴充方法。但是,編譯器生成的中間語言 (IL) 會将代碼轉換為對靜态方法的調用。是以,并未真正違反封裝原則。實際上,擴充方法無法通路它們所擴充的類型中的私有變量。

擴充方法通用準則 

1、通常,建議您隻在不得已的情況下才實作擴充方法,并謹慎地實作。隻要有可能,必須擴充現有類型的用戶端代碼都應該通過建立從現有類型派生的新類型來達到這一目的。

2、在使用擴充方法來擴充您無法更改其源代碼的類型時,您需要承受該類型實作中的更改會導緻擴充方法失效的風險。

3、如果您确實為給定類型實作了擴充方法,請記住以下兩點:

     如果擴充方法與該類型中定義的方法具有相同的簽名,則擴充方法永遠不會被調用。

     擴充方法被在命名空間級别放入範圍中。例如,如果您在同一個名為 Extensions 的命名空間中具有多個包含擴充方法的靜态類,則這些擴充方法将全部由 using Extensions; 指令放入範圍中。

本文轉自 你聽海是不是在笑 部落格園部落格,原文連結:http://www.cnblogs.com/nuaalfm/archive/2008/08/07/1262711.html  ,如需轉載請自行聯系原作者