[英]How do extension methods work with inheritance?
我知道魔法的前半部分。 假设我有:
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()
?
编译器将查找其参数与调用站点上的参数最匹配的扩展方法。 如果你有一个Bar
类型的变量,那么将使用BarExt
扩展,因为Bar
比Foo
更具体的类型,因此比采用Foo
实例的替代方法更紧密地匹配。 这与模糊方法重载的解决方式确实没有什么不同。
值得注意的是,此代码将调用FooExt.M()
:
Foo bar = new Bar();
bar.M();
这是因为扩展方法不是虚拟的。 由于您调用方法的变量是类型Foo
,因此甚至不会考虑扩展方法的Bar
版本。 扩展方法的绑定完全在编译时发生。
在你指出的第二种情况下(在Wow
类型的变量上调用扩展方法),将使用FooExt.M()
方法,因为没有更好的匹配。
我测试了它,答案是
BarExt
,但为什么呢?
因为编译器会选择“最适合”调用的扩展方法。 由于有一种直接采用Bar
的方法,因此选择了一种。
当我打电话给wow.M()时会发生什么?如果我有另一个Wow:Foo但没有WowExt.M()?
同样,它将选择“最适合”使用的扩展名。 既然没有采用Wow
方法,但确实采用它的父类Foo
它会选择FooExt.M()
请记住,扩展方法实际上只是静态方法调用的语法糖,因此相同的规则适用于它们作为“正常”方法解析。
解析扩展方法时,将选择最具体的类型匹配。 在第一种情况下, BarExt.M()
是最具体的(目标是Bar
而不是Foo
)。
在第二种情况下,没有Wow
扩展,因此最具体的匹配将是FooExt.M()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.