正如 Jared Par 已经说过的:这取决于您的个人偏好、可读性和用例。例如,如果您的方法有一些可选参数,并且您希望在给定参数的情况下过滤集合,那么Where 是完美的:
IEnumerable<SomeClass> matchingItems = allItems;
if(!string.IsNullOrWhiteSpace(name))
matchingItems = matchingItems
.Where(c => c.Name == name);
if(date.HasValue)
matchingItems = matchingItems
.Where(c => c.Date == date.Value);
if(typeId.HasValue)
matchingItems = matchingItems
.Where(c => c.TypeId == typeId.Value);
return matchingItems;
如果你想用&& 来做这件事,玩得开心;)
我不同意Jared 和Reed 的地方是多个Where 应该有的性能问题。实际上,Where 进行了优化,将多个谓词组合为一个,如您所见here(在CombinePredicates 中)。
但我想知道如果集合很大并且有多个Where 都必须进行评估,它是否真的没有太大影响。我很惊讶下面的benchmark 揭示了即使是多重Where 方法也稍微更有效。总结:
| Method |
Mean |
Error |
StdDev |
| MultipleWhere |
1.555 s |
0.0310 s |
0.0392 s |
| MultipleAnd |
1.571 s |
0.0308 s |
0.0649 s |
这是基准代码,我认为它对于这个测试来说已经足够了:
#LINQPad optimize+
void Main()
{
var summary = BenchmarkRunner.Run<WhereBenchmark>();
}
public class WhereBenchmark
{
string[] fruits = new string[] { "apple", "mango", "papaya", "banana", "guava", "pineapple" };
private IList<string> longFruitList;
[GlobalSetup]
public void Setup()
{
Random rnd = new Random();
int size = 1_000_000;
longFruitList = new List<string>(size);
for (int i = 1; i < size; i++)
longFruitList.Add(GetRandomFruit());
string GetRandomFruit()
{
return fruits[rnd.Next(0, fruits.Length)];
}
}
[Benchmark]
public void MultipleWhere()
{
int count = longFruitList
.Where(f => f.EndsWith("le"))
.Where(f => f.Contains("app"))
.Where(f => f.StartsWith("pine"))
.Count(); // counting pineapples
}
[Benchmark]
public void MultipleAnd()
{
int count = longFruitList
.Where(f => f.EndsWith("le") && f.Contains("app") && f.StartsWith("pine"))
.Count(); // counting pineapples
}
}