C#3.0擴充方法學習篇

來源:互聯網
上載者:User

標籤:

 什麼是類的擴充方法

擴充方法使您能夠向現有類型“添加”方法,而無需建立新的衍生類別型、重新編譯或以其他方式修改原始類型。

MSDN

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.

傳統的模式下如果想為一個類型(class)添加一個額外的自訂的特殊的邏輯上,或者業務上的新方法時,你必須重新定義的一個類型來繼承原有的的方法,用繼承類或者介面,但是有些用sealed修飾的,這時候就無法被繼承,例如String,實值型別,sealed修飾的類。

擴充方法是C#3.0這個版本提出來的。解決了必須由繼承才能擴充的某個類的弊端,最重要的一點就是很好用。

平時在我們使用的過程中也經常的見到,如這其中的OrderBy方法就是擴充方法。MSDN

注意:

擴充方法必須在非嵌套、非泛型的靜態類中定義。

Note that it is defined inside a non-nested<非嵌套>, non-generic<非泛型的> static<靜態> class:

擴充方法的規則有以下幾點:

  • 擴充方法必須是擴充方法必須是非嵌套、非泛型的靜態類中定義的;
  • 擴充方法的第一個參數要用this關鍵字修飾;
  • 第一個方法參數不能有ref 或則out關鍵字修飾的參數;
擴充方法的調用有兩個步驟
  1. 引用項目的命名空間;
  2. 參數調用兩種;
  • 和傳統的調用方法一樣使用<ExtendClass>.<ExtendClassMethod>(參數,參數+?)
  • <參數類型>.<ExtendClassMethod>(參數+?)
進階點的應用    在編譯時間綁定擴充方法<MSDN>    你可以使用擴充方法來擴充一個類和介面,而不需要去重寫他們
  1 // Define an interface named IMyInterface.  2 namespace DefineIMyInterface  3 {  4     using System;  5   6     publicinterface IMyInterface  7     {  8         // Any class that implements IMyInterface must define a method  9         // that matches the following signature. 10         void MethodB(); 11     } 12 } 13  14  15 // Define extension methods for IMyInterface. 16 namespace Extensions 17 { 18     using System; 19     using DefineIMyInterface; 20  21     // The following extension methods can be accessed by instances of any  22     // class that implements IMyInterface. 23     publicstaticclass Extension 24     { 25         publicstaticvoid MethodA(this IMyInterface myInterface, int i) 26         { 27             Console.WriteLine 28                 ("Extension.MethodA(this IMyInterface myInterface, int i)"); 29         } 30  31         publicstaticvoid MethodA(this IMyInterface myInterface, string s) 32         { 33             Console.WriteLine 34                 ("Extension.MethodA(this IMyInterface myInterface, string s)"); 35         } 36  37         // This method is never called in ExtensionMethodsDemo1, because each  38         // of the three classes A, B, and C implements a method named MethodB 39         // that has a matching signature. 40         publicstaticvoid MethodB(this IMyInterface myInterface) 41         { 42             Console.WriteLine 43                 ("Extension.MethodB(this IMyInterface myInterface)"); 44         } 45     } 46 } 47  48  49 // Define three classes that implement IMyInterface, and then use them to test 50 // the extension methods. 51 namespace ExtensionMethodsDemo1 52 { 53     using System; 54     using Extensions; 55     using DefineIMyInterface; 56  57     class A : IMyInterface 58     { 59         publicvoid MethodB() { Console.WriteLine("A.MethodB()"); } 60     } 61  62     class B : IMyInterface 63     { 64         publicvoid MethodB() { Console.WriteLine("B.MethodB()"); } 65         publicvoid MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); } 66     } 67  68     class C : IMyInterface 69     { 70         publicvoid MethodB() { Console.WriteLine("C.MethodB()"); } 71         publicvoid MethodA(object obj) 72         { 73             Console.WriteLine("C.MethodA(object obj)"); 74         } 75     } 76  77     class ExtMethodDemo 78     { 79         staticvoid Main(string[] args) 80         { 81             // Declare an instance of class A, class B, and class C. 82             A a = new A(); 83             B b = new B(); 84             C c = new C(); 85  86             // For a, b, and c, call the following methods://      -- MethodA with an int argument//      -- MethodA with a string argument//      -- MethodB with no argument.// A contains no MethodA, so each call to MethodA resolves to // the extension method that has a matching signature. 87             a.MethodA(1);           // Extension.MethodA(object, int) 88             a.MethodA("hello");     // Extension.MethodA(object, string)// A has a method that matches the signature of the following call// to MethodB. 89             a.MethodB();            // A.MethodB()// B has methods that match the signatures of the following// method calls. 90             b.MethodA(1);           // B.MethodA(int) 91             b.MethodB();            // B.MethodB()// B has no matching method for the following call, but // class Extension does. 92             b.MethodA("hello");     // Extension.MethodA(object, string)// C contains an instance method that matches each of the following// method calls. 93             c.MethodA(1);           // C.MethodA(object) 94             c.MethodA("hello");     // C.MethodA(object) 95             c.MethodB();            // C.MethodB() 96         } 97     } 98 } 99 /* Output:100     Extension.MethodA(this IMyInterface myInterface, int i)101     Extension.MethodA(this IMyInterface myInterface, string s)102     A.MethodB()103     B.MethodA(int i)104     B.MethodB()105     Extension.MethodA(this IMyInterface myInterface, string s)106     C.MethodA(object obj)107     C.MethodA(object obj)108     C.MethodB()109  */

 

編譯器是如何發現擴充方法的c# 3.0編譯器看到某個類的調用用法時,先是從該類的執行個體方法中進行尋找,如果沒有找到與調用方法同名並參數一致的執行個體方法,再從所有匯入的命名空間中尋找是否有合適的擴充方法,並將變數類型匹配到擴充類型。這隻是我們的理解是這樣一個過程,如果在同一個命名空間下,編譯器則會直接用當前命名空間下合格對應方法,讓我看下下ILDasm.exe.如果不是同一個程式集的命名空間可以在MANIFEST資訊清單檔裡看出。

總結的結果

方法的調用次序 類型的執行個體方法--->當前命名空間下的擴充方法--->匯入的其他命名空間擴充方法。

引發疑問

在Null 參考上調用執行個體方法或靜態方法時會拋出NullReferenceException異常?那麼在類調用擴充方法時會出現異常嗎?(不使用類中的一些屬性或方法,強調調用)

        public static void NullUse(this TestExtend sextend)        {            Console.WriteLine("NUll used Method");        }分析:在空的類型上定義擴充方法不出現NullReferenceException,只是把空這個引用當成參數傳入靜態方法,
擴充方法 靜態方法
TestExtend sExtend=null;            sExtend.NullUse(); TestExtend sExtend=null;NullUse.(sExtend);
   從ILDASM能看出我們猜想的正確性Notice

可能引發的子類汙染的問題例如

        public static bool isNull(this object str)          {            return str == null;        }

你本來只想擴充TestExtend 這個類的方法,由於你要使用iSNull這個類型的擴充結果傳入參數(object),結果導致所有的object 類型都擴充了這個方法,這會帶來可怕的後果。

所以在擴充一個類型的方法時,要從確定類型擴充。盡量避免從父類去擴充。

有什麼不對的或者錯誤的地方希望大家給予指正,謝謝

我的開發環境VS2015

DEMO的下載  【http://pan.baidu.com/s/1bY51P8】

 

C#3.0擴充方法學習篇

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.