Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩展方法如何处理继承?_C#_Inheritance_Extension Methods - Fatal编程技术网

C# 扩展方法如何处理继承?

C# 扩展方法如何处理继承?,c#,inheritance,extension-methods,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) {}

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

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
版本甚至不会被考虑。扩展方法的绑定完全发生在编译时

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

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

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

如果我有另一个wow:Foo但没有WowExt.M(),当我调用wow.M()时会发生什么

同样,它将选择“最适合”使用的扩展。因为没有方法接受
Wow
,但是一个方法接受它的父类
Foo
,它将选择
FooExt.M()


请记住,扩展方法实际上只是静态方法调用的语法糖,因此对它们应用与“普通”方法解析相同的规则。

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


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

只是一个计算的猜测,但我认为编译器会查看静态类型来选择它必须采用的类型。你试过这样的吗<代码>Foo myfoo=新条();myfoo.M()+1。由于扩展方法只是静态方法,第一个参数在函数名之前移动,所以它们使用与常规方法完全相同的规则。
Foo bar = new Bar();
bar.M();