扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
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这个版本提出来的。解决了必须由继承才能扩展的某个类的弊端,最重要的一点就是很好用。
注意:
扩展方法必须在非嵌套、非泛型的静态类中定义。
Note that it is defined inside a non-nested<非嵌套>, non-generic<非泛型的> static<静态> class:
扩展方法的规则有以下几点:
- 扩展方法必须是扩展方法必须是非嵌套、非泛型的静态类中定义的;
- 扩展方法的第一个参数要用this关键字修饰;
- 第一个方法参数不能有ref 或则out关键字修饰的参数;
- 引用项目的命名空间;
- 参数调用两种;
- 和传统的调用方法一样使用<ExtendClass>.<ExtendClassMethod>(参数,参数+?)
- <参数类型>.<ExtendClassMethod>(参数+?)
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 */
总结的结果
方法的调用次序 类型的实例方法--->当前命名空间下的扩展方法--->导入的其他命名空间扩展方法。
引发疑问
在空引用上调用实例方法或静态方法时会抛出NullReferenceException异常?那么在类调用扩展方法时会出现异常吗?(不使用类中的一些属性或方法,强调调用)
扩展方法 | 静态方法 |
TestExtend sExtend=null; sExtend.NullUse(); | TestExtend sExtend=null; NullUse.(sExtend); |
可能引发的子类污染的问题例如
你本来只想扩展TestExtend 这个类的方法,由于你要使用iSNull这个类型的扩展结果传入参数(object),结果导致所有的object 类型都扩展了这个方法,这会带来可怕的后果。
所以在扩展一个类型的方法时,要从确定类型扩展。尽量避免从父类去扩展。
有什么不对的或者错误的地方希望大家给予指正,谢谢
我的开发环境VS2015
DEMO的下载 【http://pan.baidu.com/s/1bY51P8】