2

当用流畅的语法编写时,是否有语法糖或方法可以在同一行内“短路”LINQ 语句?例如,如果nullFirstOrDefault调用返回,是否有可能返回 null 否则继续方法链的其余部分?

List<string> testList = new List<string>() { "some", "strings" };
var reversed = testList.FirstOrDefault(x => x == "hello").Reverse();

FirstOrDefault调用将返回 null,因此该语句将ArgumentNullExceptionReverse调用中抛出一个。有没有办法在调用之前停止,Reverse因为此时返回了默认值?

(我知道查询可以分成另一行并且default(T)可以在之前检查,Reverse或者对于简单的情况,?:可以使用条件运算符()但我很好奇我是否缺少更长/更复杂链的特定功能)

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

4

3 回答 3

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原始代码,因为一旦找到第一个元素,就会立即返回结果。

于 2013-08-14T15:44:33.477 回答
2

是的,只需使用 First 而不是 FirstOrDefault;它会更早地抛出异常。

于 2013-08-14T15:40:35.277 回答
2

看起来您正在寻找可能的单子的 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());

如果您的列表不包含“你好”这个词,那将输出 null 。

于 2013-08-14T15:51:14.673 回答