单声道+命名/可选参数=编译器错误?
我遇到了一些无法预料的移植到mono 2.8.1的后果。问题可以被归结为一个示例程序(I一直无法进一步降低它,切割几个类和〜1000行的代码下面引用该文件之后)单声道+命名/可选参数=编译器错误?
public class Person
{
public Person(int age, string name = null){}
public Person(double income, string name = null){}
public Person(double income, int age, string name = null){}
}
class Program
{
static void Main()
{
Person p = new Person(1.0, name: "John Doe");
}
}
编译的上面的代码与MCS给出输出:
test.cs(22,24): error CS0584: Internal compiler error: Internal error
test.cs(22,20): error CS0266: Cannot implicitly convert type `object' to `NamedParams.Person'.
An explicit conversion exists (are you missing a cast?)
Compilation failed: 2 error(s), 0 warnings
取出使用可选/命名参数(即调用新的Person(1.0,空, “李四”)或新的Person(1.0,空,名称: “李四”),或新的Person( 1.0,“John Doe”))导致了完美的编译。此外,在VS2010下,文件(以及我开始的整个解决方案)编译得很好。 Casting会移除错误CS0266,但不会移除CS0584 - 因此在那里不会感到意外。我的问题:是我做错了什么,或者mcs(即mcs中的bug对我来说很明显 - 还有什么,内部错误会是什么意思,但也许没关系,这样的程序不会编译),或者也许在VS2010中的微软编译器不应该让这样的代码编译?
我敢打赌,这是MCS谁的错(不能猜对构造函数),但也许它,否则,我不应该知道的?
PS。我尝试在Google和Novell的Bugzilla中搜索这样一个已知的bug,但无法找到任何相关的东西。再一次,我可能会失明;)
好的,这里有。事故的确是由于第三次超载,Person(double income, int age, string name = null)
。 编译器认为您正在尝试传递比签名中列出的参数少的参数,因此它会查找可选参数。它高兴地注意到name
是可选的,并假定你没有通过这个参数。它通过在所提供参数的末尾添加一个占位符来完成此操作。接下来,它会重新排列列表中的命名参数,以便它们以正确的位置结束。这意味着John Doe
现在正确地位于name
的最后位置,但占位符进入age
的位置。编译器然后尝试填写默认值,但是在没有默认值的位置找到占位符时感到震惊。它认为这不可能发生,因为占位符仅被添加用于可选参数,现在突然它不再是可选的。不知道该怎么做,它会抛出一个异常。
下面的补丁似乎解决这个问题(但它可能会导致其他问题,因此不予保修):
--- mono-2.6.7.orig/mcs/mcs/ecore.cs 2009-10-02 12:51:12.000000000 +0200
+++ mono-2.6.7/mcs/mcs/ecore.cs 2010-12-21 02:26:44.000000000 +0100
@@ -3803,6 +3803,15 @@
int args_gap = Math.Abs (arg_count - param_count);
if (optional_count != 0) {
+ // readjust for optional arguments passed as named arguments
+ for (int i = 0; i < arguments.Count; i++) {
+ NamedArgument na = arguments[i] as NamedArgument;
+ if (na == null)
+ continue;
+ int index = pd.GetParameterIndexByName (na.Name.Value);
+ if (pd.FixedParameters[index].HasDefaultValue)
+ optional_count--;
+ }
if (args_gap > optional_count)
return int.MaxValue - 10000 + args_gap - optional_count;
对于其他人来此线程。该错误仍然存在于截至2013年4月的最新版本的Mono Compiler中。我创建了一个解决方案,无需使用C#重载函数修改编译器。
Foo(int a, bool b = true) {
Foo(a, b, "Default String");
}
Foo(int a, bool b, string c)
你甚至可以设置一个字符串为空... – Blam 2010-12-20 23:55:23
有没有错误编译使用visual studio。我没有单声道来尝试它,以确认。 – 2010-12-21 00:05:54
@Courtney:单声道可在线获取[此处](http://ideone.com/kZ2Eo)。 – Vlad 2010-12-21 00:07:11