扩展方法如何与继承一起使用?

时间:2013-01-21 22:37:37

标签: c# inheritance extension-methods

我知道魔术的前半部分。假设我有:

public class Foo {}
public class static FooExt
{
    public static void M(this Foo f) {}
}

当我调用foo.M()时,编译器会将其更改为FooExt.M(foo)

但继承怎么样?例如:

public class Bar : Foo {}
public class static BarExt
{
    public static void M(this Bar b) {} 
}

当我调用bar.M()时,会调用FooExt.M()还是BarExt.M()?事实上我测试了它,答案是BarExt,但为什么呢?如果我有另一个wow.M()但没有Wow : Foo,当我致电WowExt.M()时会发生什么?

3 个答案:

答案 0 :(得分:10)

编译器将查找参数与调用站点上的最匹配的扩展方法。如果您有Bar类型的变量,则会使用BarExt扩展名,因为Bar的类型比Foo更具体,因此比其他选项更匹配采用Foo实例的方法。这与模糊方法重载的解决方法确实没有什么不同。

值得注意的是,此代码将调用FooExt.M()

Foo bar = new Bar();
bar.M();

这是因为扩展方法不是虚拟的。由于您调用方法的变量是Foo类型,因此甚至不会考虑扩展方法的Bar版本。 扩展方法的绑定完全在编译时发生。

在您指出的第二种情况下(对Wow类型的变量调用扩展方法),将使用FooExt.M()方法,因为没有更好的匹配。

答案 1 :(得分:5)

  

我测试了它,答案是BarExt,但为什么?

因为编译器会选择“最适合”调用的扩展方法。由于有一种方法直接采用Bar,因此选择了一种方法。

  

当我打电话给wow.M()时会发生什么?如果我有另一个Wow:Foo但没有WowExt.M()?

同样,它会选择“最适合”使用的扩展名。由于没有方法需要Wow,但是它确实采用了它的父类Foo,因此会选择FooExt.M()

请记住,扩展方法实际上只是静态方法调用的语法糖,因此相同的规则适用于它们作为“正常”方法解析。

答案 2 :(得分:3)

解析扩展方法时,将选择最具体的类型匹配。在第一种情况下,BarExt.M()是最具体的(Bar而不是Foo)。

在第二种情况下,没有Wow扩展名,因此最具体的匹配项为FooExt.M()