将项目从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'
是什么原因导致此问题?是否可以通过编译器设置修复它?
是什么导致此问题?
对我来说似乎是一个编译器错误。至少,确实如此。虽然decimal.TryParse(v, out a)
和decimal.TryParse(v, out b)
表现进行动态评估,我希望编译器还了解到,通过它到达的时间a <= b
,无论是a
和b
肯定分配。即使您在动态类型输入中可能会感到很奇怪,但我希望仅a <= b
在评估两个TryParse
调用之后才进行评估。
但是,事实证明,通过运算符和转换比较棘手,拥有一个表达式A && B && C
进行评估是完全可行的A
,C
但是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] 删除。
我来说两句