因为调用对象的方法时,如果该对象所属的类拥有自己的实现,则C#将解析调用到该实现而不是继承或覆盖的实现。这可能会导致微妙且难以发现的问题,就像您在此处展示的那样。
例如,请尝试以下代码(先阅读它,然后编译并执行它),看看它是否按照您期望的那样运行。
using System;
namespace ConsoleApplication9
{
public class Base
{
public virtual void Test(String s)
{
Console.Out.WriteLine("Base.Test(String=" + s + ")");
}
}
public class Descendant : Base
{
public override void Test(String s)
{
Console.Out.WriteLine("Descendant.Test(String=" + s + ")");
}
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
}
}
class Program
{
static void Main(string[] args)
{
Descendant d = new Descendant();
d.Test("Test");
Console.In.ReadLine();
}
}
}
请注意,如果您将变量的类型声明为 Base
类型而不是 Descendant
,则调用将转到另一个方法,请尝试更改此行:
Descendant d = new Descendant();
将其更改为此,并重新运行:
Base d = new Descendant();
那么,你实际上如何调用 Descendant.Test(String)
呢?
我的第一次尝试看起来是这样的:
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
Test((String)s);
}
这对我没有帮助,只会不断调用Test(Object)
导致最终栈溢出。
但是下面的代码可以工作。由于我们将变量d
声明为Base
类型时,我们最终调用了正确的虚拟方法,因此我们也可以使用这种技巧:
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
Base b = this;
b.Test((String)s);
}
这将打印出:
Descendant.Test(Object=Test)
Descendant.Test(String=Test)
你也可以从外部这样做:
Descendant d = new Descendant();
d.Test("Test");
Base b = d;
b.Test("Test");
Console.In.ReadLine();
将会打印出相同的内容。
但是首先你需要知道问题,这是完全不同的另一件事情。
MySubClass
定义上是不是忘记加上: MyClass
了? - Bruno Reis