当用流利的语法编写时,是否有语法糖或方法在同一行中“短路”LINQ语句?例如,如果null
调用返回FirstOrDefault
,是否可以返回null,否则继续使用方法链的其余部分?
List<string> testList = new List<string>() { "some", "strings" };
var reversed = testList.FirstOrDefault(x => x == "hello").Reverse();
FirstOrDefault
调用将返回null,因此该语句将在ArgumentNullException
调用上抛出Reverse
。是否有一种在Reverse
调用之前停止的方法,因为此时返回了默认值?
(我知道查询可以分解为另一行,default(T)
之前可以检查Reverse
,或者对于简单的情况,可以使用条件运算符(?:
)但是如果我错过了更长/更复杂链的特定功能,我很好奇。
编辑 - 为了澄清这只是一个展示这个想法的例子,它不是任何实际代码的一部分。我想避免抛出异常,因为分割线并进行检查会更有效。
答案 0 :(得分:4)
如果您要将集合解析为单个项目并操纵该项目,但仍能优雅地处理在集合中找不到该项目的情况,您可以延迟FirstOrDefault
直到结束,像这样:
var reversed = testList
.Where(x => x == "hello")
.Select(x => x.Reverse())
.FirstOrDefault();
或等效
var reversed = testList
.Where(x => x == "hello")
.Select(Enumerable.Reverse)
.FirstOrDefault();
如果列表中没有满足null
方法中指定条件的项,则返回Where
。这里的性能差异最多可以忽略不计。它不需要在原始代码之外循环遍历testList
,因为一旦找到第一个元素,就会立即返回结果。
答案 1 :(得分:2)
是的,只需使用First而不是FirstOrDefault;它会提前抛出异常。
答案 2 :(得分:2)
看起来你正在追逐可能是monad的C#版本。
public static class MaybeMonadExtensions
{
public static TResult GetIfNotNull<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
where TResult : class
where TInput : class
{
return o == null ? null : evaluator(o);
}
}
使用此功能,您可以编写
var reversed = testList.FirstOrDefault(x => x == "hello").GetIfNotNull(s => s.Reverse());
如果您的列表中不包含单词“hello”,则输出null。