在每次返回之前使用Where()从多个源返回第一个项
本文关键字:返回 第一个 Where | 更新日期: 2023-09-27 18:27:50
我发现了一个有趣的代码片段,它以非预期的方式使用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,这可能会有一个错误。(在大多数情况下,GetFirstString应该跳过空值)
试试这个:
string GetFirstString(){
return a.FirstOrDefault(...)
?? b.FirstOrDefault(...)
?? c.FirstOrDefault(...)
?? "";
}
string GetFirstString(){
var str = "";
if( str == null )
str = b.FirstOrDefault(...);
if( str == null )
str = b.FirstOrDefault(...);
if( str == null )
str = c.FirstOrDefault(...);
return str;
}
这在我看来有点难看,因为它引入了一个变量并改变了方法的整个结构。
您可以使用Concat
将所有内容连接到一个序列中,然后选择First
。
var list = a.Where(...)
.Concat(b.Where(...))
.Concat(c.Where(..))
.Take(1)
.ToList();//Make sure we execute the query only once.
if(list.Count > 0)
return list[0];
return "";
注意:您可能认为Take(1)
、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 "";
}
您可以使用Union
扩展方法
string GetFirstString()
{
return a.Where(...)
.Union(b.Where(...))
.Union(c.Where(...)).FirstOrDefault();
}