问题描述
using System;
using static System.Console;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Test.Starttest();
ReadLine();
}
}
public class Test
{
class SomeResult {}
class BaseClass
{
public virtual TResult DoSomething<TResult>()
{
WriteLine(nameof(BaseClass));
return default;
}
}
class DerivedClass : BaseClass
{
public override TResult DoSomething<TResult>()
{
WriteLine(nameof(DerivedClass));
Func<TResult> baseImplementation = base.DoSomething<TResult>;
//This works: return base.DoSomething<TResult>();
return baseImplementation();
}
}
public static void Starttest()
{
DerivedClass instance = new DerivedClass();
instance.DoSomething<SomeResult>();
//This works: instance.DoSomething<int>();
WriteLine("Finished");
}
}
}
基本上,我在类 BaseClass
中有 DerivedClass
和 BaseClass
(它派生自 Test
)(我认为前面的类在里面并不重要) Test
,但我会保持原样,以防我遗漏了什么)。
BaseClass
具有虚拟方法 DoSomething
,DerivedClass
重写该方法以调用基类实现,但通过创建 Func
委托“指向”{{ 1}},并调用该委托(考虑到这只是一个准系统示例,并不完全是我在实际项目中想要完成的)。
运行程序时,会创建一个 BaseClass.DoSomething
实例,并调用其 DerivedClass
方法,该方法应通过前面提到的委托调用 DoSomething
。当我在 Visual Studio 中运行它时,它按我的预期工作,确实调用了 BaseClass.DoSomething
(输出为“DerivedClass BaseClass Finished”)。但是,在其他地方(Unity 游戏引擎,但不相关)运行它时,委托不会调用 BaseClass.DoSomething
,而是调用 BaseClass.DoSomething
(进入循环并导致堆栈溢出异常)。用“//This works:”注释掉的行不会发生这种情况,即使我认为它们大部分是等效的。
预期的行为不会是调用委托总是执行 DerivedClass.DoSomething
,还是我遗漏了一些东西,这是一个实现细节,而不是语言中定义明确的规则?我的第一个假设是这是 Unity 或它使用的 Mono 版本中的错误,但我不确定是否还有其他需要考虑的问题。
解决方法
行为必须是委托执行基类方法,而不是派生类方法。我收到了来自 Unity 的确认,即向后行为确实是一个错误。