我遇到了移植到单声道2.8.1的一些无法预料的后果。问题可以归结为一个示例程序(在将几个类和〜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
删除使用可选/命名参数(即调用new Person(1.0,null,“John Doe”)或新Person(1.0,null,name:“John Doe”)或新Person(1.0,“John Doe) “))导致完美的编译。此外,在VS2010下,文件(以及我开始使用的整个解决方案)编译得很好。 Casting删除了错误CS0266,但没有删除CS0584 - 所以不用担心。
我的问题:我做错了什么,或者是mcs(即mcs中的bug对我来说是显而易见的 - 还有什么内部错误''意味着,但也许这样程序无法编译),或者也许VS2010中的Microsoft编译器不应该让这样的代码编译?
我敢打赌,这是mc谁错了(无法猜出正确的构造函数),但也许不是这样,我不应该知道更好?
PS。我试图在Google和Novell的Bugzilla中搜索这样的已知错误,但无法找到任何相关内容。再说一遍,我可能会失明;)
答案 0 :(得分:3)
好的,到此为止。崩溃确实是由于第三次重载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;
答案 1 :(得分:0)
对于其他人来到这个主题。截至2013年4月,Mono Compiler的最新版本中仍然存在该错误。我创建了一个无需使用C#重载函数修改编译器的工作。
Foo(int a, bool b = true) {
Foo(a, b, "Default String");
}
Foo(int a, bool b, string c)