擴展方法使您可以向現有類型「添加」方法,而無需建立新的派生類型、從新編譯或以其餘方式修改原始類型。c#
MSDNide
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.this
傳統的模式下若是想爲一個類型(class)添加一個額外的自定義的特殊的邏輯上,或者業務上的新方法時,你必須從新定義的一個類型來繼承原有的的方法,用繼承類或者接口,可是有些用sealed修飾的,這時候就沒法被繼承,例如String,值類型,sealed修飾的類。spa
擴展方法是C#3.0這個版本提出來的。解決了必須由繼承才能擴展的某個類的弊端,最重要的一點就是很好用。code
注意:blog
擴展方法必須在非嵌套、非泛型的靜態類中定義。繼承
Note that it is defined inside a non-nested<非嵌套>, non-generic<非泛型的> static<靜態> class:接口
擴展方法的規則有如下幾點:three
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 */
總結的結果ci
方法的調用次序 類型的實例方法--->當前命名空間下的擴展方法--->導入的其餘命名空間擴展方法。
引起疑問
在空引用上調用實例方法或靜態方法時會拋出NullReferenceException異常?那麼在類調用擴展方法時會出現異常嗎?(不使用類中的一些屬性或方法,強調調用)
擴展方法 | 靜態方法 |
TestExtend sExtend=null;
sExtend.NullUse();
|
TestExtend sExtend=null;
NullUse.(sExtend);
|
可能引起的子類污染的問題例如
你原本只想擴展TestExtend 這個類的方法,因爲你要使用iSNull這個類型的擴展結果傳入參數(object),結果致使全部的object 類型都擴展了這個方法,這會帶來可怕的後果。
因此在擴展一個類型的方法時,要從肯定類型擴展。儘可能避免從父類去擴展。
有什麼不對的或者錯誤的地方但願你們給予指正,謝謝
個人開發環境VS2015
DEMO的下載 【http://pan.baidu.com/s/1bY51P8】