这是一个关于表现的问题。以下是我在自己的代码和同事代码中看到的模式
var items = GetItems();
变量items
现在包含一个IQueryable
,它将从数据库返回一行,多行或没有行。
然后:
if (items.Any()) {
//do something, but only if there are items
foreach (var item in items) {
...
}
//do something else, but only if there are items
}
因此,如果有项目,我们将执行两个动作和一个循环。假设通常是返回的项目,将上述代码编辑为更有意义:
var items = GetItems().ToList();
所以我的Any()
(有时甚至是.Count() > 0
)
您如何看待这个?假设GetItems()返回一个复杂的查询,这个查询本身并不慢,但仍然很复杂。
答案 0 :(得分:2)
如果性能至关重要并且您不希望一次性将所有内容加载到内存中,则可以使用这种不需要多次执行查询的方法:
bool anyItems = false; bool firstItem = true;
foreach (var item in items)
{
anyItems = true;
if(firstItem)
{
//do something, but only if there are items and only once
firstItem = false;
}
// do something with this item
}
if(anyItems)
{
//do something else, but only if there are items
}
如果您不希望使用ToList
多个项目,那么您就不需要关心多个Any
或Count
来电,您甚至可以访问给定索引处的项目(for循环中的fe)。
所以ToList
会花费内存,但
使用IQueryable
可以节省内存,但
items.Any
可能会在以后产生不同的结果)答案 1 :(得分:1)
你最好这样做:
bool anyItems = false;
foreach (var item in items) {
anyItems = true;
// do stuff
}
这样你只执行一次查询而不是一次将所有项目都拉入内存。如果你真的不需要知道是否有物品 - 你可以删除anyItems
旗帜。
如果你需要在处理项目之前做一些事情 - 在循环的第一次迭代中执行此操作,然后再处理第一项:
bool firstItem = true;
foreach (var item in items) {
if (firstItem) {
// do something, but only if there are items
firstItem = false;
}
// handle item
}
如果这会带来很多好处,取决于你的情况。如果您不期望成千上万的项目 - 您可以使用ToList
。如果您希望很多这些查询返回0项 - 您可能更喜欢进行Any
次查询,但前提是它们要快得多(您应该自己测量)。如果您不希望大多数查询返回0项 - 最好始终使用此方法(或ToList
)来保存一个数据库查询。