3

我刚刚输入了以下代码:

Expression<Func<ContentItem, bool>> expression = 
                fileTypeGroupID.HasValue ? n => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value : n => true;

Visual Studio 说它无法推断n.

代码对我来说似乎很好 - 它只是使用三元运算符将两个Expression文字之一分配给一个Expression变量。

Visual Studio 是不是不够聪明,无法推断出n三元运算符内部的类型,还是我犯了某种错误?

4

3 回答 3

13

这个问题几乎每天都以某种形式被问到。

条件运算符类型分析从进行,而不是从。条件运算符不知道将其结果分配给什么类型,然后强制结果和替代这些类型。它恰恰相反;它计算出结果和替代的类型,采用这两种类型中更一般的类型,然后验证可以分配一般类型。

结果和替代不包含有关 lambda 应该是什么类型的信息,因此无法推断条件的类型。因此无法验证分配是否正确。

考虑一下为什么要这样设计语言是很有启发性的。假设您有重载:

 void M(Func<string, int> f) {}
 void M(Func<double, double> f) {}

和一个电话

M( b ? n=>n.Foo() : n => n.Bar() );

描述在从外到内推断类型的世界中,重载决策如何确定选择 M 的哪个重载。

现在考虑这个:

M( b1 ? (b2 ? n=>n.Foo() : n => n.Bar() ) : (b3 ? n=>n.Blah() : n=>n.Abc()) );

是不是越来越难了?现在想象一下 Foo、Bar、Blah 和 Abc 本身就是接受 func 的方法,并且还有带有包含 lambda 的条件运算符的参数。

我们不希望类型推断过程如此复杂而没有相应的巨大好处,而条件运算符也没有如此巨大的好处。

在您的情况下,您应该做的是将结果中的一个或两个强制转换为特定类型。

于 2011-12-14T15:10:29.523 回答
2

这并不能回答您为什么编译器无法推断类型的问题,但一个简单的解决方法是这样编写您的表达式:

Expression<Func<ContentItem, bool>> expression = 
  n => !fileTypeGroupID.HasValue || n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value;
于 2011-12-14T15:19:09.250 回答
1
fileTypeGroupID.HasValue ? (ContentItem n) => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value
                         : (ContentItem n) => true;

请注意,条件运算符是它的正确名称,? :它是三元运算符的示例(并且是许多编程语言中唯一的三元运算符)。

于 2011-12-14T15:07:28.897 回答