扩展方法解决问题:以往对已存在的类库进行扩展,可行的方式直接对源代码进行修改或者直接派生。
扩展方法注意事项:
- 扩展方法必须被定义在一个静态类中,扩展方法自身必须是一个静态方法;
- 扩展方法中的首个参数必须是this,最后紧跟要扩展的类的名称;
- 扩展方法可以被对象实例调用,也可以使用静态类名进行静态调用。
扩展方法的使用范围:
实例调用:
namespace ExtensionMethodObjects { //1,定义一个静态类 public static class ExtensionMethods { //2,定义一个静态方法,该方法扩展object对象。 /* * 扩展方法的的参数部分:第一个参数必须为THIS * 然后跟随要扩展的类型名称和标识值 */ public static void SayHello(this object obj) { Console.WriteLine("扩展方法!"); } } }
namespace ExtensionMethodObjects { class Program { static void Main(string[] args) { //实例化一个object类型的对象 object o = new object(); o.SayHello(); } } }
静态调用:
namespace InvokeExtensionMethods { //注意类的可见性级别,必须要在整个应用程序范围可见。 public static class ExtensionMethods { //扩展int类型,为其添加一个反转整数的能力。 public static int ReverseDigits(this int i) { char[] digits = i.ToString().ToCharArray(); Array.Reverse(digits); string newDigits = new string(digits); return int.Parse(newDigits); } //扩展Car类,为其添加一个SpeedDown方法 public static int SpeedDown(this Car car) { //这样写将会产生一个编译时错误 //return --Speed; //正确的方法应该是car.Speed; return --car.Speed; } } }
namespace InvokeExtensionMethods { class Program { static void Main(string[] args) { int i = 123456; //实例方法调用,直接用扩展的类的对象实例来进行调用 Console.WriteLine("实例方法调用,反转后的值为:{0}", i.ReverseDigits()); //静态方法调用,通过调用扩展方法的静态类名再加扩展方法进行调用 Console.WriteLine("静态方法调用,反转后的值为:{0}", ExtensionMethods.ReverseDigits(i)); } } //定义一个简单的汽车类 public class Car { public int Speed; public int SpeedUp() { return ++Speed; } } }
推荐采用实例方法调用,编译器实际上将实例调用编译成静态方法的调用。
扩展方法的地雷区:
- 扩展方法的名称不能与被扩展的类相同,否者扩展方法不能被调用。
因为编译时,扩展方法的优先级总是比类型本身中定义的实例方法级别低,其实意思就是类中有一个具有相同签名的扩展方法,编译器总是绑定到该实例方法,当编译器需要调用方法时,首先在该类型的实例方法中寻找匹配的方法。如果未找到任何匹配方法 ,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到得第一个扩展方法。
- 不能在扩展方法中直接访问扩展方法扩展的类的成员变量,由于扩展方法是静态方法,并不属于类成员中的标准方法,因此不能直接进行访问。可参见上面例子中的静态调用。
- 如果扩展方法与被扩展的方法具有不同的命名空间,需要在调用扩展方法时引用定义扩展方法的命名空间。