c# - Roslyn 编译代码失败

标签 c# .net linq roslyn

在我将我的项目从 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();
}

编译器返回错误:

Error CS0165 Use of unassigned local variable 'b'

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

最佳答案

What does cause this issue?

在我看来像是一个编译器错误。至少,它做到了。虽然decimal.TryParse(v, out a)decimal.TryParse(v, out b)表达式是动态求值的,我期望编译器在它到达 a <= b 时仍能理解这一点, 两者 ab肯定被分配了。即使你在动态类型中可能会遇到一些奇怪的事情,我也希望只评估 a <= b在评估了 TryParse 之后电话。

然而,事实证明,通过运算符和转换技巧,表达式A && B && C是完全可行的。评估AC但不是 B - 如果你足够狡猾。查看Roslyn bug report Neal Gafter 的巧妙示例。

让它与 dynamic 一起工作更难 - 操作数是动态的时涉及的语义更难描述,因为为了执行重载决议,您需要评估操作数以找出涉及的类型,这可能是违反直觉的。然而,Neal 再次提出了一个示例,表明编译器错误是必需的……这不是一个错误,而是一个错误修复。 Neal 证明了这一点,获得了巨大的荣誉。

Is it possible to fix it through compiler settings?

不,但是有其他方法可以避免错误。

首先,您可以阻止它成为动态的 - 如果您知道您只会使用字符串,那么您可以使用 IEnumerable<string> 给出范围变量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 标准中解决这个问题。

关于c# - Roslyn 编译代码失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31961411/

相关文章:

c# - 为什么这个 UWP Binding to decimal property 不能正常工作?

.net - 如何在 NHibernate 中使用带有枚举属性的 ICriteria

.net - 使用 Microsoft.Web.Administration 远程管理 IIS 时身份验证期间出现 COMException

c# - linq按子字符串对数组中的字符串进行排序

c# - 特殊文件夹

c# - 检查一个列表是否包含另一个列表中的任何元素

.net - DataGridView 过滤器忽略单元格、单词上的变音符号(重音)

c# - TakeWhile,但也获取停止它的元素

c# - Linq-to-SQL 结合两个 Expression<Func<T, bool>> ("where clause") 与 and/or

c# - WPF复选框双向绑定(bind)不起作用