扩展方法使您可以向现有类型“添加”方法,而无需建立新的派生类型、从新编译或以其余方式修改原始类型。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】