为什么我得到这个编译错误试图调用一个基本的构造函数/方法,需要一个dynamic的参数?

在重构一些代码时,我遇到了这个奇怪的编译错误:

构造函数调用需要dynamic调度,但不能因为它是构造函数初始值设定项的一部分。 考虑转换dynamic参数。

当试图调用带有dynamic参数的基本方法/构造函数时,似乎会发生这种情况。 例如:

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) 

所以,我有点困惑。 为什么我不得不把这个讨厌的演员放在 – 为什么编译器不知道我的意思?

构造函数链必须在编译时确定 – 编译器必须select一个重载,以便它可以创build有效的IL。 通常,重载parsing(例如,方法调用)可以被推迟到执行时间,这对链式构造函数调用不起作用。

编辑:在“正常”的C#代码(在C#4之前,基本上), 所有的重载parsing在编译时执行。 但是,当成员调用涉及dynamic值时,在执行时parsing。 例如考虑这个:

 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)它不知道要解决哪个超载。 相反,它会发出一些代码,这些代码会执行一些“及时”的小型编译,以便在执行时用d实际值来parsing超载。

现在,这不适用于构造函数链,因为有效的IL必须包含对特定基类构造函数的调用。 (我不知道这个dynamic版甚至不能 IL来表示 ,或者它是否可以,但结果是不可证实的。)

你可以争辩说,C#编译器应该能够告诉实际上只有一个可以被调用的可见的构造函数,并且这个构造函数总是可用的…但是一旦你开始了这条路,你最终会得到一种语言指定非常复杂。 C#devise人员通常会采取简单的规则,偶尔没有你想要的那么强大。