为什么'Submissions.Where(s =>(false&& s.Status == Convert.ToInt16(“”)))'引发FormatException?

时间:2009-06-16 13:14:07

标签: c# linq

我认为这个查询非常简单,但它提出了一个FormatException(“输入字符串的格式不正确”):

Submissions.Where(s => (false && s.Status == Convert.ToInt16("")))

(当然,在我的代码中,另一个评估为'false'的表达式位于'&&'之前)

那么为什么'&&'之后的部分呢?评估,因为第一部分总是假的,总表达式永远不能评估为true

情况特别奇怪,因为只有Convert.ToInt16("")部分似乎引发异常 - 我原始查询的其他部分或多或少相同的结构,如

Submissions.Where(s => (false && s.SubmissionDate <= DateTime.Now))

正确评估。

4 个答案:

答案 0 :(得分:6)

正如其他人所指出的那样,LINQ to SQL代码在作为针对数据库的SQL代码运行之前被拆分为表达式树。由于SQL不一定遵循与C#相同的短路布尔规则,因此可能会解析表达式代码的右侧,以便可以构造SQL。

来自MSDN

  

C#指定短路语义   基于操作数的词汇顺序   逻辑运算符&amp;&amp;和||。 SQL上   另一方面是针对性的   基于集合的查询,因此   为...提供更多自由   优化器来决定顺序   执行。

至于你为什么要使用这个代码获得异常,Convert.ToInt16("")将始终精确地抛出该异常,因为无法将空字符串转换为整数。您的另一个示例不会尝试无效转换,因此它运行没有问题。

答案 1 :(得分:5)

如果SubmissionsIQueryable<T>,那么这不是常规的C#委托,而是表达式树。一些代码(LINQ提供者)必须将这个树分开并理解它 - 所以如果你在表达式中有奇怪的东西,那么期望奇数输出。

答案 2 :(得分:2)

根据您在评论中对我的问题的回答,因为它是Linq to Sql,它实际上不是委托。我尝试使用Linq to Objects重新创建它,确实没有任何问题。 VS实际上指出“检测到无法访问的代码”。因为在你的情况下,它实际上是Linq to Sql,然后它正在构建一个表达式树,在这种情况下它必须解密所有这些并且所有的赌注都关闭。

答案 3 :(得分:0)

建议:使用静态Int16来保存Convert.ToInt16(“”)的结果,然后引用谓词中的static。

更好的是,你知道Convert.ToInt16(“”)的结果是什么吗?是?然后用它代替。例如,如果它是0,那么说s.Status == 0.你甚至可以使它成为常数。