Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单声道+;命名/可选参数=编译器错误?_C#_.net_C# 4.0_Mono - Fatal编程技术网

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

C# 单声道+;命名/可选参数=编译器错误?,c#,.net,c#-4.0,mono,C#,.net,C# 4.0,Mono,我在移植到mono 2.8.1时遇到了一些无法预料的后果。这个问题可以归结为一个示例程序(在将几个类和~1000行代码剪切到下面引用的文件后,我无法进一步减少它) 用mcs编译上述代码可得到以下输出: test.cs(22,24): error CS0584: Internal compiler error: Internal error test.cs(22,20): error CS0266: Cannot implicitly convert type `object' to `Named

我在移植到mono 2.8.1时遇到了一些无法预料的后果。这个问题可以归结为一个示例程序(在将几个类和~1000行代码剪切到下面引用的文件后,我无法进一步减少它)

用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”)或new Person(1.0,null,name:“John Doe”)或new Person(1.0,John Doe))的使用将导致完美的编译。此外,在VS2010下,文件(以及我开始使用的整个解决方案)可以很好地编译。强制转换会删除错误CS0266,但不会删除CS0584——所以这并不奇怪

我的问题:是我做错了什么,还是mcs(即mcs中的错误对我来说是显而易见的——还有什么,内部错误“”可能意味着什么,但也许这样的程序不会编译没关系),或者VS2010中的Microsoft编译器不应该让这样的代码编译

我打赌是mcs错了(无法猜出正确的构造函数),但也许是其他原因,我不应该知道得更清楚


另外,我试着在Google和Novell的Bugzilla中搜索一个已知的bug,但是找不到任何相关的。再说一次,我可能是瞎子;)

好了,开始吧。这次崩溃确实是由于第三次过载,
Person(双倍收入,整数年龄,字符串名=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);
如果(可选_计数!=0){
+//重新调整作为命名参数传递的可选参数
+for(int i=0;i可选计数)
返回int.MaxValue-10000+参数间隔-可选计数;

供其他人使用。截至2013年4月,Mono编译器的最新版本中仍然存在该漏洞。我创建了一个变通方法,无需使用C#重载函数修改编译器

Foo(int a, bool b = true) {
    Foo(a, b, "Default String");
}

Foo(int a, bool b, string c)

您甚至可以将字符串设置为null…使用visual studio编译此字符串时没有错误。但我没有mono来尝试确认。@Courtney:mono在线可用。mono 2.6.7在mono.CSharp.MethodGroupExpr.IsAppliebleSure中也会崩溃。在我看来,mono看起来像是一个mono bug。注意,mono也可以使用命名参数,但您有要删除最后一个重载(
个人(双倍收入,整数年龄,字符串名称=null)
重载)。显然Mono与重载解析混淆了,重载解析涉及在调用中使用可选参数和命名参数。或者其他。您的答案是否也适用于Mono-2.8.1?我不知道您是否知道,并且默默地假设,或者您忽略了我使用2.8.1的事实?AFAIR 2.6.7完全支持命名/可选参数,但我不知道代码本身是否已更改…不知道。由于两个版本显示相同的崩溃,我认为这也适用于2.8.1。但是,我这里只有2.6.7,因此无法测试。
--- 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;
Foo(int a, bool b = true) {
    Foo(a, b, "Default String");
}

Foo(int a, bool b, string c)