C#mono出现奇怪的编译器错误
我有以下代码:C#mono出现奇怪的编译器错误,c#,compiler-errors,mono,C#,Compiler Errors,Mono,我有以下代码: int? sum=Enumerable.Range(0, 1000).Sum((i) => { if (((i % 3) == 0) && ((i % 5) == 0)) return i; return null; }); 此代码未编译,它生成以下错误: 错误CS0266:无法将类型“decimal”隐式转换为“int”。存在显式转换(是否缺少
int? sum=Enumerable.Range(0, 1000).Sum((i) =>
{
if (((i % 3) == 0) && ((i % 5) == 0))
return i;
return null;
});
此代码未编译,它生成以下错误:
错误CS0266:无法将类型“decimal”隐式转换为“int”。存在显式转换(是否缺少强制转换?)
我将代码更改为:
int? sum=Enumerable.Range(0, 1000).Sum<int>((int i) =>
{
if (((i % 3) == 0) && ((i % 5) == 0))
return i;
return null;
});
int?总和=可枚举范围(0,1000)。总和((整数i)=>
{
如果((i%3)==0)和((i%5)==0))
返回i;
返回null;
});
但编译器错误仍然存在
我不明白,Enumerable.Range
返回一组整数,很明显我想要返回int的Sum
,否则,i
应该是decimal
,正如我所说,在i
之前插入int
并不重要
当我将sum
adecimal?
变量设置为它编译的变量时
我想这可能是一个单声道错误,我在错误列表中没有看到类似的东西
那么,我是遗漏了什么,还是应该提交一个bug
我的mono版本是4.4.1,我的操作系统是Arch linux x64。肯定是个bug,因为VisualStudio附带的编译器不会出现这种情况 mono的一个解决方法似乎是返回
default(int?
而不是null
int? sum=Enumerable.Range(0, 1000).Sum((i) =>
{
if (((i % 3) == 0) && ((i % 5) == 0))
return i;
return default(int?);
});
下面是一个简化的测试程序,它演示了BCL之外的问题:
using System;
using static System.Console;
static class Program {
static void Test1(Func<int?> f) { WriteLine("Test1(Func<int?>)"); }
static void Test1(Func<decimal?> f) { WriteLine("Test1(Func<decimal?>)"); }
static void Test2(Func<decimal?> f) { WriteLine("Test2(Func<decimal?>)"); }
static void Test2(Func<int?> f) { WriteLine("Test2(Func<int?>)"); }
static void Main() {
Test1(() => null);
Test2(() => null);
}
}
使用系统;
使用静态系统控制台;
静态类程序{
静态void Test1(Func f){WriteLine(“Test1(Func)”;}
静态void Test1(Func f){WriteLine(“Test1(Func)”;}
静态void Test2(Func f){WriteLine(“Test2(Func)”;}
静态void Test2(Func f){WriteLine(“Test2(Func)”;}
静态void Main(){
Test1(()=>null);
Test2(()=>null);
}
}
当使用Mono(4.4)编译时,它会打印:
Test1(Func<decimal?>)
Test2(Func<int?>)
Test1(Func<int?>)
Test2(Func<int?>)
Test1(Func)
测试2(Func)
使用Roslyn编译时,此文件将打印:
Test1(Func<decimal?>)
Test2(Func<int?>)
Test1(Func<int?>)
Test2(Func<int?>)
Test1(Func)
测试2(Func)
在讨论C#5.0语言规范时,最终应该选择哪种重载可以归结为7.5.3.3更好地从表达式转换,但它没有解决这个问题。它给出了一些特定的场景,其中一个重载优于另一个重载,但要在这里工作,它需要根据它所称的推断返回类型进行操作。但是,null
没有类型。没有推断的返回类型。这使得我们在语言规范中没有描述要使用哪个重载的内容
5.0语言规范称该调用不明确。编译器应生成一个错误。
不幸的是,语言规范没有描述微软的编译器。这迫使Mono实施丑陋的黑客攻击,试图模仿微软的行为,因为拒绝编译使用微软编译器编译的代码是一种让人们不把Mono当回事的简单方法,正如你在回答这个问题时看到的那样。这些丑陋的黑客不是完美的,除非规范正确描述了他们设计的语言,否则可能永远也不会完美 一个非官方的C#6.0语言规范已在上公布。它描述了重载解析规则的一些调整(查看7.5.3.3更好的表达式转换和7.5.3.5更好的转换目标):
是比int?
更好的转换目标,因为存在从decimal?
到int?
的隐式转换,但不是相反decimal?
- 因此,
是比Func
更好的转换目标Func
- 因此,从
到()=>null
的转换比Func
好Func
不管你是将其视为解决Mono bug或缺少的功能,还是将其视为修复代码以使其更兼容C#5.0,结果都是一样的:使用
default(int?
,而不是Steve建议的null
,都会使其工作。在C#5.0中,它的工作方式是给匿名函数一个推断的返回类型int?
,以有利于所需重载的方式解决歧义。从:(int i)到:(int)i@jdweng我不明白你的意思。然后,向mono报告错误:在dotnetfiddle中,你的代码没有错误。@x。。。谢谢,我刚刚做了“肯定是个bug,因为VisualStudio附带的编译器不会出现这种情况。”——C#应该由语言规范定义。这种语言规范没有明确说明某些事情。如果是这样,那么代码中的错误就是依赖于未指定的行为。虽然我怀疑语言规范确实定义了行为,并以与对待它相同的方式对其进行了定义,但答案应该真正显示语言规范(或MS文档)在何处定义了哪些Sum
重载应被称为“语言规范未描述Microsoft的编译器”因此,如果我使用visual studio 2013(或者更具体地说是旧版编译器,它不是Roslyn),我会得到相同的编译器错误@niceman我相当肯定旧版编译器和C#5.0规范不匹配,甚至在规范允许之前,它已经按照您期望的方式工作了。如果可以,我会做一个快速检查。@niceman使用.NET Framework提供的csc.exe,它不实现C#6.0,并抱怨我的使用static
,更改后,我的答案中的代码被标记为不明确。但是,如果我将()=>null
更改为()=>{return 0;return null;}
类似于您所拥有的,那么