单声道+命名/可选参数=编译器错误?

时间:2010-12-20 23:51:47

标签: c# .net c#-4.0 mono

我遇到了移植到单声道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中搜索这样的已知错误,但无法找到任何相关内容。再说一遍,我可能会失明;)

2 个答案:

答案 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)