我找到了一个有趣的代码片段,它使用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?
更新:
如果任何列表包含空条目且Where谓词允许空条目通过,则可能有错误,然后它将返回null。 (在大多数情况下,GetFirstString应该跳过空值)
答案 0 :(得分:3)
试试这个:
string GetFirstString(){
return a.FirstOrDefault(...)
?? b.FirstOrDefault(...)
?? c.FirstOrDefault(...)
?? "";
}
答案 1 :(得分:1)
您可以使用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
。
答案 2 :(得分:1)
string GetFirstString(){
var str = "";
if( str == null )
str = b.FirstOrDefault(...);
if( str == null )
str = b.FirstOrDefault(...);
if( str == null )
str = c.FirstOrDefault(...);
return str;
}
这对我来说似乎很难看,因为它引入了一个变量并改变了方法的整个结构。
答案 3 :(得分:0)
使用FirstOrDefault()而不是First()
string GetFirstString(){
if (a.Any(...))
return a.FirstOrDefault(...);
if (b.Any(...))
return b.FirstOrDefault(...);
if (c.Any(...))
return c.FirstOrDefault(...);
return "";
}
答案 4 :(得分:-1)
您可以使用Union
扩展方法
string GetFirstString()
{
return a.Where(...)
.Union(b.Where(...))
.Union(c.Where(...)).FirstOrDefault();
}