扩展方法(深入理解c#)
1. 静态类到扩展方法:
许多方法可能都适合转为扩展方法,只要具有以下特征:
1)你想为一个类型添加一些成员;
2)你不需要为类型的实例添加更多的数据;
3)你不能改变类型本身,因为是别人的代码
2.声明扩展方法
并不是任何方法都能作为扩展方法使用——他必须具有以下特征:
1)他必须在一个非嵌套的,非泛型的静态类中(所以必须是一个静态方法);
2)他至少要有一个参数;
3)第一个参数必须附加this关键字作为前缀;
4)第一个参数不能有其他任何修饰符(比如out或ref);
5)第一个参数不能是指针类型;
我们将第一个参数的类型称为方法的扩展类型,即指该方法扩展了该类型,代码:
public static class StreamUtil
{
const int BufferSize = 8192;
public static void CopyTo(this Stream input,Stream output)
{
byte[] buffer = new byte[BufferSize];
int read;
while((read = input.Read(buffer,0,buffer.Length)) > 0)
{
output.Write(buffer,0,read);
}
}
}
调用:
Stream responseStream = new Stream();
responseStream.CopyTo();
3. 扩展方法是怎样被发现的
知道怎样调用扩展方法固然重要,但知道怎样不调用同样重要。换言之,你要知道如何实现“非请勿来”。
首先了解编译器怎样决定要使用的扩展方法
如果使用using指令,扩展方法可以像类一样不加限制的在代码中使用。如果编译器认为一个表达式好像是要使用一个实例方法,但没有找到与这个方法调用兼容的实例方法(名称不兼容或参数不兼容)。就会查找一个合适的扩展方法。塔会检查导入的所有命名空间和当前命名空间的所有扩展方法,并匹配那些从表达式类型到扩展类型存在着隐式转换的扩展方法。(编译器怎么找到库中的扩展方法:它会检查类和方法是否具有System.Runtime.CompilerServices.ExtensionAttribute这个特性,它是.NET3.5新增的。但是,编译器不检查特性来自哪个程序集,这意味着即使你的项目面向的是.NET2.0,仍然可以使用扩展方法——只需在正确的命名空间中使用正确的名称来定义自己的属性就可以了(即自己编写一个System.Runtime.CompilerServices.ExtensionAttribute类))
如果存在多个适用的扩展方法,他们可应用于不同的扩展类型(使用隐式转换),那么将使用在重载的方法中应用的 “更好的转换” 规则,来选择最合适的方法。
要注意的一个重点是,如果存在适当的实例方法,则实例方法肯定会先于扩展方法使用。
在c#中,你不能在空引用上调用实例方法,但你可以在空引用上调用扩展方法。
4. 使用思路和原则
如果你觉得代码最重要的就是他的结果,扩展方法肯定相当和你胃口,如果觉得实现更重要,那么显式调用静态方法就显得更清晰,实际上,这是“是什么”和“怎么做“之间的差异