在迄今爲止的內容中,每個方法都和聲明它的類關聯,擴展方法特性擴展了這個邊界,允許編寫的方法和聲明它的類之外的類關聯
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
}
}