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

C# 如果在任意点返回默认值,则停止LINQ查询,c#,linq,default-value,syntactic-sugar,short-circuiting,C#,Linq,Default Value,Syntactic Sugar,Short Circuiting,当用流利的语法编写LINQ语句时,是否有语法糖分或方法在同一行中“短路”LINQ语句?例如,如果FirstOrDefault调用返回null,是否可以返回null,否则继续方法链的其余部分 List<string> testList = new List<string>() { "some", "strings" }; var reversed = testList.FirstOrDefault(x => x == "hello").Reverse(); List

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

List<string> testList = new List<string>() { "some", "strings" };
var reversed = testList.FirstOrDefault(x => x == "hello").Reverse();
List testList=newlist(){“some”,“strings”};
var reversed=testList.FirstOrDefault(x=>x==“hello”).Reverse();
FirstOrDefault
调用将返回null,因此语句将在
Reverse
调用上抛出
ArgumentNullException
。由于在该点返回了默认值,是否有方法在调用
Reverse
之前停止

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


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

是的,只需使用First而不是FirstOrDefault;它将在更早的时候抛出异常。

如果您想将集合解析为单个项并操作该项,但仍能优雅地处理集合中可能找不到该项的情况,您可以将
FirstOrDefault
延迟到最后,如下所示:

var reversed = testList
    .Where(x => x == "hello")
    .Select(x => x.Reverse())
    .FirstOrDefault();
或同等地

var reversed = testList
    .Where(x => x == "hello")
    .Select(Enumerable.Reverse)
    .FirstOrDefault();

如果列表中没有满足
Where
方法中指定条件的项,则返回
null
。这里的性能差异最多可以忽略不计。与原始代码相比,它不需要在
测试列表中循环,因为一旦找到第一个元素,结果就会立即返回。

看起来您在寻找C版本的maybe monad

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);
    }
}

如果列表中没有“hello”这个词,那么它将输出null。这没有意义-
FirstOrDefault()
将只返回一个元素,因此
Reverse()
在这里没有意义。。。你想做什么?那只是一个公认的人为的例子。实际上我并没有这样做,也没有做任何特别的事情,但这只是一个应该返回null的场景,而不是继续沿着方法链进行。感谢您的回复,但这并不是我真正想要的避免异常的想法。如果要处理异常,可以在反向调用时执行,或者最好从性能的角度来看,将查询拆分为多行。我应该在我的问题中澄清这一点。很遗憾,答案是否定的。你似乎在问性能问题,从性能的角度来看,抛出的异常实际上是最优的。如果您知道这确实是该块中出现错误的唯一原因,只需将catch完全保留为空,甚至不要定义异常的类型并让它消除错误。澄清一下:拆分查询并执行If/then检查是否为空比仅消除异常要差得多。@wilso132:我不同意。如果他希望更多的时候不被发现,然后再被发现,或者“没有结果”的比率相当高,那么异常可能会对性能产生影响。此外,Linq通常在被枚举(即foreach循环)或转换为某种东西(
.ToArray()
.ToList()
)@Tseng我理解你的论点,但我认为它不正确。您建议检查.Any()(发出查询)然后执行另一个函数(在某个时候必须发出另一个查询),这比处理甚至不使用引用的异常要密集得多。如果他期望有很多例外情况,你的观点是正确的,但我认为必须超过50%的情况。我认为OP只是给出了一些例子来说明问题,我想他可能想给出另一个例子,因为这个可以通过这个来解决。@ReedCopsey,因为我们想反转字符串,汉克斯,我已经澄清了我的问题。King是对的,这只是一个很容易解决的例子,但我对这个问题的实际解决方案不感兴趣。我想知道是否有一种语言功能,在任意点上,可以在中途检测到一个默认值,然后停止LINQ查询的其余部分。@keyboardP,这个解决方案就是这样做的。如果未找到任何项,则不会执行
反向操作
(或在
.FirstOrDefault
之后执行的任何操作)。实际上,这正是
FirstOrDefault
所做的。这就是为什么它比
SingleOrDefault
性能更好的原因。
var reversed = testList.FirstOrDefault(x => x == "hello").GetIfNotNull(s => s.Reverse());