Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Where()foreach Return从多个源返回第一项_C#_Linq - Fatal编程技术网

C# 使用Where()foreach Return从多个源返回第一项

C# 使用Where()foreach Return从多个源返回第一项,c#,linq,C#,Linq,我发现了一个有趣的代码片段,它以非预期的方式使用Where和foreach。然而,它们的使用似乎是一个非常有趣的解决方案,可以显著减少代码行 // a, b, c are IEnumerable<string> of any data source and could be expensive to iterate string GetFirstString(){ foreach( var str in a.Where(...) ) return str;

我发现了一个有趣的代码片段,它以非预期的方式使用Where和foreach。然而,它们的使用似乎是一个非常有趣的解决方案,可以显著减少代码行

// a, b, c are IEnumerable<string> of any data source and could be expensive to iterate
string GetFirstString(){

    foreach( var str in a.Where(...) )
        return str;

    foreach( var str in b.Where(...) )
        return str;

    foreach( var str in c.Where(...) )
        return str;

    return "";

} 
有没有更好的方法来做到这一点,它同样简短,但不滥用Where和foreach

更新:

如果任何列表包含null条目,并且Where谓词允许null条目通过,那么它将返回null,这可能会有一个bug。在大多数情况下,GetFirstString应该跳过空值

您可以使用Concat将所有内容连接到单个序列,然后选择第一个

注意:您可能认为Take1、ToList和返回列表中的第一个元素似乎是多余的,您可以将其更改为FirstOrDefault。但这改变了代码的语义。问题是,当过滤后的序列包含null时,FirstOrDefault??将返回空字符串,但OP的原始代码将返回null。

您可以使用Concat将所有内容连接到单个序列,然后选择第一个


注意:您可能认为Take1、ToList和返回列表中的第一个元素似乎是多余的,您可以将其更改为FirstOrDefault。但这改变了代码的语义。问题是,当过滤后的序列包含null时,FirstOrDefault??将返回空字符串,但OP的原始代码将返回null。

使用FirstOrDefault而不是First

string GetFirstString(){

        if (a.Any(...))
           return a.FirstOrDefault(...);

        if (b.Any(...))
           return b.FirstOrDefault(...);

        if (c.Any(...))
           return c.FirstOrDefault(...);

        return "";

    } 

使用FirstOrDefault而不是First

string GetFirstString(){

        if (a.Any(...))
           return a.FirstOrDefault(...);

        if (b.Any(...))
           return b.FirstOrDefault(...);

        if (c.Any(...))
           return c.FirstOrDefault(...);

        return "";

    } 
试试这个:

string GetFirstString(){
    return a.FirstOrDefault(...) 
        ?? b.FirstOrDefault(...) 
        ?? c.FirstOrDefault(...)
        ?? "";
}
试试这个:

string GetFirstString(){
    return a.FirstOrDefault(...) 
        ?? b.FirstOrDefault(...) 
        ?? c.FirstOrDefault(...)
        ?? "";
}
这对我来说有点难看,因为它引入了一个变量并改变了方法的整体结构

这对我来说有点难看,因为它引入了一个变量并改变了方法的整个结构。

您可以使用联合扩展方法

string GetFirstString()
{
    return a.Where(...)
        .Union(b.Where(...))
        .Union(c.Where(...)).FirstOrDefault();
}
您可以使用联合扩展方法

string GetFirstString()
{
    return a.Where(...)
        .Union(b.Where(...))
        .Union(c.Where(...)).FirstOrDefault();
}


另外,如果每个Where中的表达式都是相同的OP,我没有提到,但我敢打赌它们是相同的,我会先做所有的concats:a.Concatb.Concatc.Where….FirstOrDefault,在返回前检查null值,如果是,则返回。最后这似乎有点太复杂了。从Take1和下面,它可以替换为FirstOrDefault@RickLove你可以用FirstOrDefault替换它吗??但若列表包含null值,则返回的不是null值。如果可以的话,那么你可以。这就是我选择不使用FirstOrDefault的原因:。另外,如果每个Where中的表达式都是相同的OP没有提到,但很有可能它们是相同的,我只会首先执行所有Concat:a.Concatb.Concatc.Where….FirstOrDefault,在返回之前检查值是否为null,如果是,则返回。这在结尾处似乎有点过于复杂。从Take1和以下,它可以替换为FirstOrDefault@RickLove你可以用FirstOrDefault替换它吗??但若列表包含null值,则返回的不是null值。如果可以,那么您可以。这就是我选择不使用FirstOrDefault的原因:。这将迭代每个数据源twice@RickLove不,它不需要,这取决于数据源。它不会迭代整个序列,但最好只传递Any。。。第一个或默认值的谓词。。。如果FirstOrDefault。。。当然,返回null。@DavidPilkington好的,它可以,对于潜在的昂贵调用,应该避免这种情况。尽管如此,这确实让我想知道不同的数据源如何处理任何…这是错误的。Any将检查谓词匹配,但首先选择列表中的第一个元素,而不考虑谓词。这将迭代每个数据源twice@RickLove不,它不需要,这取决于数据源。它不会迭代整个序列,但最好只传递Any。。。第一个或默认值的谓词。。。如果FirstOrDefault。。。当然,返回null。@DavidPilkington好的,它可以,对于潜在的昂贵调用,应该避免这种情况。尽管如此,这确实让我想知道不同的数据源如何处理任何…这是错误的。Any将检查谓词匹配,但首先会选择列表中的第一个元素,而不考虑谓词。啊,你比我先找到它。注意:这确实稍微改变了逻辑-如果任何列表包含null值,谓词允许null值,那么它将返回,而原始foreach解决方案将返回null。啊,注意:这确实稍微改变了逻辑-如果任何列表包含null值并且谓词允许null值,那么它将返回,而原始foreach解决方案将返回null。Union将比较所有项以检查不同的值。这将是非常昂贵的。Concat可以。Union将比较所有项目以检查不同的值。这将是非常昂贵的。连接两个字符串 好的。