在迄今为止的内容中,每个方法都和声明它的类关联,扩展方法特性扩展了这个边界,允许编写的方法和声明它的类之外的类关联
class MyData
{
private double D1;
private double D2;
private double D3;
public MyData(double d1,double d2,double d3)
{
D1 = d1;D2 = d2;D3 = d3;
}
public double Sum()
{
return D1 + D2 + D3;
}
}
如上面的代码所示,这是一个有限的类,假设它还需要含有另一个方法,这个方法返回3个数据的平均值,则有这几种方法可以实现:
(1)如果有源代码,只需要添加一个新方法即可
(2)如果不能修改这个类(如这个类在一个第三方类库中),那么只要它不是密封的,你就能把它用作一个基类在派生自它的类中实现这个额外的方法。
(3)如果不能访问代码,或者该类是密封的,就不得不在另一个类中使用该类的公有可用成员编写一个方法,例如可以编写一个下面这样的类,该类中方法接受MyData的实例作为参数来完成相应的需求。
static class ExtendMyData
{
public static double Average(MyData md)
{
return md.Sum() / 3;
}
}
class Program
{
static void Main(string[] args)
{
MyData md = new MyData(3, 4, 5);
Console.WriteLine(ExtendMyData.Average(md));
}
}
尽管这是非常好的解决方案,但如果能在类的实例自身上调用该方法会更优雅,也就是第二种调用方法。
ExtendMyData.Average(md); //静态调用形式
md.Average(); //实例调用形式
而扩展方法允许你使用第二种形式,通过对Average的声明做一个改动,就可以使用实例调用形式,做法就是在参数声明中的类型前增加关键字this,如下面所示,把this加到静态类的静态方法的第一个参数上,把该方法从类ExtendMyData的常规方法改变为类MyData的扩展方法,现在俩种调用形式都可以使用。
static class ExtendMyData
{
public static double Average(this MyData md)
{
return md.Sum() / 3;
}
public static double foo(this MyData md,int i)
{
return md.Sum()+i;
}
}
class Program
{
static void Main(string[] args)
{
MyData md = new MyData(3, 4, 5);
Console.WriteLine(ExtendMyData.Average(md)); //4
Console.WriteLine(md.Average()); //4
Console.WriteLine(md.foo(100)); //112
}
}