如何使用条件三元运算符在lambdas之间有条件地分配Func <>?
通常,使用条件运算符的时候,这里的语法:如何使用条件三元运算符在lambdas之间有条件地分配Func <>?
int x = 6;
int y = x == 6 ? 5 : 9;
没什么特别的,非常直截了当。
现在,让我们尝试在将Lambda分配给Func类型时使用它。让我来解释:
Func<Order, bool> predicate = id == null
? p => p.EmployeeID == null
: p => p.EmployeeID == id;
这是相同的语法和应该工作?对?由于某些原因,不。编译器提供了这个漂亮的神秘消息:
错误不能确定1型条件表达式,因为有“lambda表达式”和“lambda表达式”
然后我继续和之间的隐式转换改变了语法和这种方式做工作:
Func<Order, bool> predicate = id == null
? predicate = p => p.EmployeeID == null
: predicate = p => p.EmployeeID == id;
我只是好奇,为什么它不工作的第一种方式?
(附注:我结束了不需要的代码,因为我发现,对比较空的int值时,你只需要使用的Object.Equals)
您可以lambda表达式转换为特定目标委托类型,但为了确定条件表达式的类型,编译器需要知道每个第二个和第三个操作数的类型。虽然它们都只是“lambda表达式”,但它们之间没有转换,所以编译器不能做任何有用的事情。
使用赋值我不会建议,但是 - 铸造更加明显:
Func<Order, bool> predicate = id == null
? (Func<Order, bool>) (p => p.EmployeeID == null)
: p => p.EmployeeID == id;
请注意,您只需要为一个操作数提供,所以编译器可以从其他执行转换lambda表达式。
C#编译器无法推断创建的lambda表达式的类型,因为它先处理三元组,然后再处理分配。你也可以这样做:
Func<Order, bool> predicate =
id == null ?
new Func<Order,bool>(p => p.EmployeeID == null) :
new Func<Order,bool>(p => p.EmployeeID == id);
但只是很烂, 你也可以尝试
Func<Order, bool> predicate =
id == null ?
(Order p) => p.EmployeeID == null :
(Order p) => p.EmployeeID == id;
让我有我自己的例子,因为我有同样的问题,太(与希望的例子对其他人有帮助):
我的Find
方法是获取Expression<Func<T, bool>>
作为谓词并给出List<T>
作为输出的一般方法。
我想查找国家,但是如果语言列表为空,并且过滤列表(如果语言列表已填写),我需要所有国家/地区。 首先,我使用的代码如下:
var countries=
Find(languages.Any()
? (country => languages.Contains(country.Language))
: (country => true));
但正是我得到的错误:there is no implicit conversion between lambda expression and lambda expression.
的问题是,我们只有两个拉姆达在这里表达,而不是其他,例如,是什么country => true
究竟是什么?我们必须确定至少一个lambda表达式的类型。如果只有一个表达式被确定,那么错误将被省略。但为使代码的可读性,我提取两个lambda表达式,和所使用的变量,而不是,如下:
Expression<Func<Country, bool>> getAllPredicate = country => true;
Expression<Func<Country, bool>> getCountriesByLanguagePredicate = country => languages.Contains(country.Language);
var countries= Find(languages.Any()
? getCountriesByLanguagePredicate
: getAllPredicate);
我强调的是,如果我刚确定的表达式的类型中的一个,该错误将被固定。
我想知道,如果编译器可以推断出这个:`Func predicate = p => p.EmployeeID == id`,怎么会有这个麻烦推断这个:`Func predicate = id == null ? (函数)(p => p.EmployeeID == null) :p => p.EmployeeID == id;`?我的意思是它知道第二个和第三个操作数通过`predicate`声明需要的类型。 –
GDS
2016-10-17 09:48:57
@GDS:有一个从lambda表达式到委托类型的隐式转换,这就是第一个版本工作的原因。但是`predicate`的声明不会影响条件表达式的类型推断。语言规范基本上说,条件表达式的类型只能通过操作数来推断。 – 2016-10-17 10:07:11