扩展方法提供了类似动态语言的特性,在保持原有类型不做更改的情况下,可以对其功能进行扩展,使系统更容易添加新的功能。简单的样例如下(其中使用了.NET Framework 3.5 中的自动属性和对象初始化器的新特性):
using System; using System.Collections.Generic; using System.Linq; using System.Text;
// 扩展 方法简单演示 namespace MyConsoleApplication { class Program { static void Main(string [] args) { // 利用对象初始化器 MyClass myClass = new MyClass { Name = "First Class" , Age = 10 }; Console .WriteLine(myClass.Read()); Console .WriteLine(myClass.Read("Second Class" )); Console .Read(); } }
public class MyClass { // 自动属性 public string Name { get ; set ; }
public int Age { get ; set ; }
public string Read() { return string .Format("Name:{0} | Age:{1}" , Name, Age.ToString()); } }
public static class MyClassExt { public static string Read(this MyClass myClass, string name) { myClass.Name = name; return myClass.Read(); } } }
结果显示: Name:First Class | Age:10 Name:Second Class | Age:10 |
从样例中可以看出,扩展方法的 定义很简单,就是写在静态类 中的静态方法 (两个条件缺一不可)。与普通静态方法不同的是,扩展方法最少需要一个参数,就是第一个形参必须为this 关键字加上要扩展的类型的参数,其他地方与普通方法定义没有区别。
————————— 华丽的分割线 ——————————
简单总结:
1. 扩展方法的调用就是通过实例方法调用语法 来 调用静态方法。
2. 扩展方法的本质是编译期技术 , 在编译时把对实例方法的调用改变为对静态类中静态方法的调用。通过反编译查看IL 代码,编译器在扩 展方法上自动加上了Extension 特性。特别要注意扩展方法与运行时技术 (如反射)的区别。
3. 扩展方法的作用域是整个命名空间可见,可通过引用其他命名空间导入其他的扩展方法(通过引用不同的命名空间来更换实现是否可以成为系统扩展的另一种方法?思考ing... )。
————————— 再次出现的分割线 ——————————
扩展方法的执行优先级:
1. 最高优先级:实例方法。样例代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text;
// 扩展 方法优先级演示 // 实例 方法优先于扩展方法 namespace MyConsoleApplication { class Program { static void Main(string [] args) { // 利用对象初始化器 MyClass myClass = new MyClass { Name = "First Class" , Age = 10 }; Console .WriteLine(myClass.Read()); Console .WriteLine(myClass.Read()); Console .Read(); } }
public class MyClass { // 自动属性 public string Name { get ; set ; }
public int Age { get ; set ; }
public string Read() { return string .Format("Name:{0} | Age:{1}" , Name, Age.ToString()); } }
public static class MyClassExt { public static string Read(this MyClass myClass) { myClass.Name = "Second Class" ; return myClass.Read(); } } }
结果显示: Name:First Class | Age:10 Name:First Class | Age:10 |
2. 临近命名空间中的扩展方法。
3. 较远命名空间中的扩展方法。样例如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text;
// 扩展 方法优先级演示 // 临近 命名空间中的扩展方法优先于 // 较远 命名空间中的扩展方法 using MyExtension1;
namespace MyConsoleApplication { using MyExtension2;
class Program { static void Main(string [] args) { // 利用对象初始化器 MyClass myClass = new MyClass { Name = "First Class" , Age = 10 }; Console .WriteLine(myClass.Read()); Console .WriteLine(myClass.Read("Second Class" )); Console .Read(); } }
public class MyClass { // 自动属性 public string Name { get ; set ; }
public int Age { get ; set ; }
public string Read() { return string .Format("Name:{0} | Age:{1}" , Name, Age.ToString()); } } }
namespace MyExtension1 { using MyConsoleApplication;
public static class MyClassExt1 { public static string Read(this MyClass myClass, string name) { myClass.Name = name + " in MyExtension1" ; return myClass.Read(); } } }
namespace MyExtension2 { using MyConsoleApplication;
public static class MyClassExt2 { public static string Read(this MyClass myClass, string name) { myClass.Name = name + " in MyExtension2" ; return myClass.Read(); } } }
结果显示: Name:First Class | Age:10 Name:Second Class in MyExtension2 | Age:10 |
即:文件级别的命名空间引用为较远的命名空间;命名空间级别的命名空间引用为邻近的命名空间。