在重构一些代码时,我遇到了这个奇怪的编译错误:
构造函数调用需要动态分派,但不能这样做,因为它是构造函数初始值设定项的一部分。考虑强制转换动态参数。
当尝试调用采用动态参数的基本方法/构造函数时,似乎会发生这种情况。例如:
class ClassA
{
public ClassA(dynamic test)
{
Console.WriteLine("ClassA");
}
}
class ClassB : ClassA
{
public ClassB(dynamic test)
: base(test)
{
Console.WriteLine("ClassB");
}
}
如果我将参数转换为object
, 像这样:
public ClassB(dynamic test)
: base((object)test)
所以,我有点困惑。为什么我必须放入这个令人讨厌的转换 - 为什么编译器不能弄清楚我的意思?
构造函数链必须在编译时确定——编译器必须选择一个重载,以便它可以创建有效的 IL。虽然通常可以将重载解析(例如方法调用)推迟到执行时间,但这对于链式构造函数调用不起作用。
编辑:在“普通”C# 代码中(基本上在 C# 4 之前),all重载决策在编译时执行。但是,当成员调用涉及动态值时,该值将在执行时解析。例如考虑这个:
using System;
class Program
{
static void Foo(int x)
{
Console.WriteLine("int!");
}
static void Foo(string x)
{
Console.WriteLine("string!");
}
static void Main(string[] args)
{
dynamic d = 10;
Foo(d);
}
}
编译器不会直接调用Foo
在这里 - 不能,因为在通话中Foo(d)
它不知道它将解决哪个过载。相反,它会发出代码,执行某种“及时”迷你编译,以解决重载问题actual值的类型d
在执行时。
现在这不适用于构造函数链接,因为有效的 IL 必须包含对特定基类构造函数的调用。 (不知道动态版是不是也不能表达在 IL 中,或者是否可以,但结果将无法验证。)
您可能会争辩说,C# 编译器应该能够知道实际上只有一个可见的构造函数can被调用,并且该构造函数将always可用...但是一旦你开始走这条路,你最终会得到一种语言very指定起来很复杂。 C# 设计者通常采取的立场是采用更简单的规则,但这些规则有时并不像您希望的那么强大。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)