不能使用三元运算符来分配Linq表达式

时间:2011-12-14 15:06:27

标签: c# linq type-inference linq-expressions

我刚输入以下代码:

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

Visual Studio说它无法推断出n的类型。

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

Visual Studio是不是很聪明,不能推断出三元运算符中n的类型,还是我犯了某种错误?

3 个答案:

答案 0 :(得分:12)

几乎每天都会以某种形式询问这个问题。

条件运算符类型分析从内部进入外部,而不是外部内部。条件运算符不知道分配其结果的类型然后强制结果和替代这些类型。它恰恰相反;它计算出结果和替代的类型,采用这两种类型中较为通用的类型,然后验证可以分配一般类型。

结果和替代方案不包含关于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本身就是采用funcs的方法,并且还有包含lambdas的条件运算符的参数。

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

在您的案例中您应该做的是投射特定类型的结果和替代方案中的一个或两个。

答案 1 :(得分:2)

这并没有回答你为什么编译器无法推断出类型的问题,但一个简单的解决办法就是用这种方式编写你的表达式:

Expression<Func<ContentItem, bool>> expression = 
  n => !fileTypeGroupID.HasValue || n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value;

答案 2 :(得分:1)

fileTypeGroupID.HasValue ? (ContentItem n) => n.Document.MimeType.FileTypeGroupID == fileTypeGroupID.Value
                         : (ContentItem n) => true;

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