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

Lai*_*uan 2 c# inheritance extension-methods

我知道魔法的前半部分.假设我有:

public class Foo {}
public class static FooExt
{
    public static void M(this Foo f) {}
}
Run Code Online (Sandbox Code Playgroud)

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

但继承怎么样?例如:

public class Bar : Foo {}
public class static BarExt
{
    public static void M(this Bar b) {} 
}
Run Code Online (Sandbox Code Playgroud)

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

cdh*_*wie 10

编译器将查找其参数调用站点上的参数最匹配的扩展方法.如果你有一个类型的变量,Bar那么BarExt将使用扩展,因为Bar它比一个类型更具体Foo,因此比采用Foo实例的替代方法更紧密地匹配.这与模糊方法重载的解决方式确实没有什么不同.

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

Foo bar = new Bar();
bar.M();
Run Code Online (Sandbox Code Playgroud)

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

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


D S*_*ley 5

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

因为编译器会选择"最适合"调用的扩展方法.由于存在Bar直接采用的方法,因此选择该方法.

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

同样,它将选择"最适合"使用的扩展名.因为没有方法需要a Wow,但是Foo它会选择它的父类FooExt.M()

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