Roslyn无法编译代码

ramil89:

将项目从VS2013迁移到VS2015后,该项目将不再生成。以下LINQ语句中发生编译错误:

static void Main(string[] args)
{
    decimal a, b;
    IEnumerable<dynamic> array = new string[] { "10", "20", "30" };
    var result = (from v in array
                  where decimal.TryParse(v, out a) && decimal.TryParse("15", out b) && a <= b // Error here
                  orderby decimal.Parse(v)
                  select v).ToArray();
}

编译器返回错误:

错误CS0165使用未分配的局部变量'b'

是什么原因导致此问题?是否可以通过编译器设置修复它?

乔恩·斯基特(Jon Skeet):

是什么导致此问题?

对我来说似乎是一个编译器错误。至少,确实如此。虽然decimal.TryParse(v, out a)decimal.TryParse(v, out b)表现进行动态评估,我希望编译器还了解到,通过它到达的时间a <= b,无论是ab肯定分配。即使您在动态类型输入中可能会感到很奇怪,但我希望仅a <= b在评估两个TryParse调用之后才进行评估

但是,事实证明,通过运算符和转换比较棘手,拥有一个表达式A && B && C进行评估是完全可行的AC但是B如果您足够狡猾的话,就不可行有关Neal Gafter的巧妙示例,请参阅Roslyn错误报告

使其工作dynamic更加困难-操作数动态时涉及的语义更难描述,因为为了执行重载解析,您需要评估操作数以找出涉及的类型,这可能是违反直觉的。但是,Neal再次提出了一个示例,该示例表明需要编译器错误...这不是错误,而是错误修复尼尔(Neal)证明了这一点非常感谢。

是否可以通过编译器设置修复它?

否,但是有其他选择可以避免该错误。

首先,您可以阻止它动态化-如果您知道只使用字符串,则可以使用IEnumerable<string> 给range变量v指定类型string(即from string v in array)。那将是我的首选。

如果您真的需要保持动态,只需给b一个值就可以开始:

decimal a, b = 0m;

这不会造成任何伤害-我们知道您的动态评估实际上不会做任何疯狂的事情,因此您最终仍将b在使用之前为其分配一个值,从而使初始值无关紧要。

此外,似乎也可以加上括号:

where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)

这改变了触发各种重载解析的时间点,并且碰巧使编译器满意。

仍然存在一个问题- &&需要明确说明规范与运算符的明确分配规则,以表明它们仅在将&&运算符用于其具有两个bool操作数的“常规”实现中时才适用我将尝试确保为下一个ECMA标准修复此问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章