如果在任何点返回默认值,则停止LINQ查询

时间:2013-08-14 15:36:02

标签: c# linq default-value syntactic-sugar short-circuiting

当用流利的语法编写时,是否有语法糖或方法在同一行中“短路”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,或者对于简单的情况,可以使用条件运算符(?:)但是如果我错过了更长/更复杂链的特定功能,我很好奇。

编辑 - 为了澄清这只是一个展示这个想法的例子,它不是任何实际代码的一部分。我想避免抛出异常,因为分割线并进行检查会更有效。

3 个答案:

答案 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。