问题描述
在以下代码中:
public abstract class MyClass
{
public abstract bool MyMethod(
Database database,
AssetDetails asset,
ref string errorMessage);
}
public sealed class MySubClass : MyClass
{
public override bool MyMethod(
Database database,
AssetDetails asset,
ref string errorMessage)
{
return MyMethod(database, asset, ref errorMessage);
}
public bool MyMethod(
Database database,
AssetBase asset,
ref string errorMessage)
{
// work is done here
}
}
其中 AssetDetails 是 AssetBase 的子类.
where AssetDetails is a subclass of AssetBase.
为什么第一个 MyMethod 在运行时在传递 AssetDetails 时调用第二个,而不是陷入无限的递归循环?
Why does the first MyMethod call the second at runtime when passed an AssetDetails, rather than getting stuck in an infinite loop of recursion?
推荐答案
C# 将解析您对其他实现的调用,因为调用对象上的方法,该对象的类有自己的实现将优于覆盖或继承一个.
C# will resolve your call to your other implementation because calls to a method on an object, where the class for that object has its own implementation will be favored over an overridden or inherited one.
这可能会导致微妙且难以发现的问题,就像您在此处展示的那样.
This can lead to subtle and hard-to-find problems, like you've shown here.
例如,试试这段代码(先阅读它,然后编译并执行它),看看它是否符合您的预期.
For instance, try this code (first read it, then compile and execute it), see if it does what you expect it to do.
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
类型,则调用将转到另一个方法,请尝试更改此行:
Note that if you declare the type of the variable to be of type Base
instead of Descendant
, the call will go to the other method, try changing this line:
Descendant d = new Descendant();
到这里,然后重新运行:
to this, and re-run:
Base d = new Descendant();
那么,那么,您将如何真正设法调用 Descendant.Test(String)
?
So, how would you actually manage to call Descendant.Test(String)
then?
我的第一次尝试是这样的:
My first attempt looks like this:
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
Test((String)s);
}
这对我没有好处,而是一次又一次地调用 Test(Object)
以导致最终的堆栈溢出.
This did me no good, and instead just called Test(Object)
again and again for an eventual stack overflow.
但是,以下工作.因为,当我们将 d
变量声明为 Base
类型时,我们最终调用了正确的虚拟方法,我们也可以使用这个技巧:
But, the following works. Since, when we declare the d
variable to be of the Base
type, we end up calling the right virtual method, we can resort to that trickery as well:
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)
您也可以从外部执行此操作:
you can also do that from the outside:
Descendant d = new Descendant();
d.Test("Test");
Base b = d;
b.Test("Test");
Console.In.ReadLine();
将打印出相同的内容.
但是首先你需要意识到问题,这完全是另一回事.
But first you need to be aware of the problem, which is another thing completely.
这篇关于为什么这行得通?方法重载+方法覆盖+多态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!