从 child class 调用基础 class 的扩展方法
Calling an extention method of a base class from child class
为什么在 child class 中,我不能通过直接调用基 class 来调用为派生 class 定义的扩展方法(我得到一个编译基础 class 不包含扩展方法定义的错误)。
但是相反,当我直接从 child 实例调用它时,我可以调用扩展方法而不会出现任何编译错误。
以下是我的问题的代码:
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
Child child = new Child();
child.TestMethod();
}
}
// Derived class
public class Mother
{
}
// Child class
public class Child : Mother
{
public Child() : base()
{
}
public void TestMethod()
{
this.ExtentionMethod(3);// Ok: no compile errors
base.ExtentionMethod(3);// Ko: Compilation error (line 27, col 8): 'Mother' does not contain a definition for 'ExtentionMethod'
}
}
public static class Extender
{
public static void ExtentionMethod(this Mother mother, int i)
{
Console.WriteLine($"Mother extention method {i}");
}
}
当您调用扩展方法时,编译器会查看左侧引用的类型并找到最合适的方法。所以当你调用this.ExtentionMethod
时,使用this
的类型来寻找最好的方法
因此在您的情况下,编译器将查找第一个参数为 Child
的扩展。由于没有,它将找到第一个参数为 Mother
的那个(因为 Child
"is-a" Mother
)。
使用 base
不会进行转换 - 它用于访问基 class 的成员。由于扩展方法不是 "members",因此 base
不会执行您期望的操作。
替代方法可能是 cast this
到基础 class 代替:
((Mother)this).ExtentionMethod(3);
虽然我会注意到您没有 不同的 派生 class 扩展方法,因此对于您发布的内容,this.ExtensionMethod
和 ((Mother)this).ExtensionBethod
。将调用相同的方法(具有相同的输入值)。
这是对 的扩展。
如果您在 Mother
和 Child
上都有扩展方法,如下所示:
public static class Extender
{
public static void ExtentionMethod(this Mother mother, int i)
{
Console.WriteLine($"Mother extention method {i}");
}
public static void ExtentionMethod(this Child child, int i)
{
Console.WriteLine($"Child extention method {i}");
}
}
然后从 sub-class 和 base-class.
调用它是有区别的
从里面Child
this.ExtentionMethod(3);
将调用 Child
版本。
((Mother)this).ExtentionMethod(3);
将调用 Mother
版本。
public void TestMethod()
{
this.ExtentionMethod(3);
((Mother)this).ExtentionMethod(3);
}
将使用上面的两种扩展方法产生以下输出:
child extention method 3
Mother extention method 3
其他答案提供了很好的解释为什么你有问题,我想确保你知道摆脱困境的最快方法:
public void TestMethod()
{
this.ExtentionMethod(3);
Extender.ExtentionMethod((Mother)this, 3);
}
如果您的编译器无法识别扩展方法,只需删除该语法糖即可。您仍然可以像常规的 public 静态方法一样调用它并传递参数,就像扩展方法的 this
关键字从未存在过一样。不是or,还是走老路吧
为什么在 child class 中,我不能通过直接调用基 class 来调用为派生 class 定义的扩展方法(我得到一个编译基础 class 不包含扩展方法定义的错误)。 但是相反,当我直接从 child 实例调用它时,我可以调用扩展方法而不会出现任何编译错误。 以下是我的问题的代码:
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
Child child = new Child();
child.TestMethod();
}
}
// Derived class
public class Mother
{
}
// Child class
public class Child : Mother
{
public Child() : base()
{
}
public void TestMethod()
{
this.ExtentionMethod(3);// Ok: no compile errors
base.ExtentionMethod(3);// Ko: Compilation error (line 27, col 8): 'Mother' does not contain a definition for 'ExtentionMethod'
}
}
public static class Extender
{
public static void ExtentionMethod(this Mother mother, int i)
{
Console.WriteLine($"Mother extention method {i}");
}
}
当您调用扩展方法时,编译器会查看左侧引用的类型并找到最合适的方法。所以当你调用this.ExtentionMethod
时,使用this
的类型来寻找最好的方法
因此在您的情况下,编译器将查找第一个参数为 Child
的扩展。由于没有,它将找到第一个参数为 Mother
的那个(因为 Child
"is-a" Mother
)。
使用 base
不会进行转换 - 它用于访问基 class 的成员。由于扩展方法不是 "members",因此 base
不会执行您期望的操作。
替代方法可能是 cast this
到基础 class 代替:
((Mother)this).ExtentionMethod(3);
虽然我会注意到您没有 不同的 派生 class 扩展方法,因此对于您发布的内容,this.ExtensionMethod
和 ((Mother)this).ExtensionBethod
。将调用相同的方法(具有相同的输入值)。
这是对
如果您在 Mother
和 Child
上都有扩展方法,如下所示:
public static class Extender
{
public static void ExtentionMethod(this Mother mother, int i)
{
Console.WriteLine($"Mother extention method {i}");
}
public static void ExtentionMethod(this Child child, int i)
{
Console.WriteLine($"Child extention method {i}");
}
}
然后从 sub-class 和 base-class.
调用它是有区别的从里面Child
this.ExtentionMethod(3);
将调用 Child
版本。
((Mother)this).ExtentionMethod(3);
将调用 Mother
版本。
public void TestMethod()
{
this.ExtentionMethod(3);
((Mother)this).ExtentionMethod(3);
}
将使用上面的两种扩展方法产生以下输出:
child extention method 3
Mother extention method 3
其他答案提供了很好的解释为什么你有问题,我想确保你知道摆脱困境的最快方法:
public void TestMethod()
{
this.ExtentionMethod(3);
Extender.ExtentionMethod((Mother)this, 3);
}
如果您的编译器无法识别扩展方法,只需删除该语法糖即可。您仍然可以像常规的 public 静态方法一样调用它并传递参数,就像扩展方法的 this
关键字从未存在过一样。不是or,还是走老路吧