.NET、.Contains() 和 .Count() 哪个更快?
我想将修改记录的数组与从数据库中提取的记录列表进行比较,并从数据库中删除传入数组中不存在的那些记录。修改后的数组来自维护数据库的客户端应用程序,并且此代码在 WCF 服务应用程序中运行,因此如果客户端从数组中删除一条记录,则应从数据库中删除该记录。以下是示例代码片段:
public void UpdateRecords(Record[] recs)
{
// look for deleted records
foreach (Record rec in UnitOfWork.Records.ToList())
{
var copy = rec;
if (!recs.Contains(rec)) // use this one?
if (0 == recs.Count(p => p.Id == copy.Id)) // or this one?
{
// if not in the new collection, remove from database
Record deleted = UnitOfWork.Records.Single(p => p.Id == copy.Id);
UnitOfWork.Remove(deleted);
}
}
// rest of method code deleted
}
我的问题:使用 Count 方法相对于 Contains 方法是否有速度优势(或其他优势)? Id 属性保证是唯一的并标识该特定记录,因此您不需要进行按位比较,正如我假设 Contains 可能会做的那样。
有人吗? 谢谢,戴夫
I want to compare an array of modified records against a list of records pulled from the database, and delete those records from the database that do not exist in the incoming array. The modified array comes from a client app that maintains the database, and this code runs in a WCF service app, so if the client deletes a record from the array, that record should be deleted from the database. Here's the sample code snippet:
public void UpdateRecords(Record[] recs)
{
// look for deleted records
foreach (Record rec in UnitOfWork.Records.ToList())
{
var copy = rec;
if (!recs.Contains(rec)) // use this one?
if (0 == recs.Count(p => p.Id == copy.Id)) // or this one?
{
// if not in the new collection, remove from database
Record deleted = UnitOfWork.Records.Single(p => p.Id == copy.Id);
UnitOfWork.Remove(deleted);
}
}
// rest of method code deleted
}
My question: is there a speed advantage (or other advantage) to using the Count method over the Contains method? the Id property is guaranteed to be unique and to identify that particular record, so you don't need to do a bitwise compare, as I assume Contains might do.
Anyone?
Thanks, Dave
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这会更快:
这与使用
Count()
具有相同的优点 - 但与Count()
不同,它也会在找到第一个匹配项后停止 >This would be faster:
This has the same advantages as using
Count()
- but it also stops after it finds the first match unlikeCount()
您甚至不应该考虑
Count
,因为您只是检查记录是否存在。您应该使用Any
来代替。使用
Count
强制迭代整个枚举以获得正确的计数,Any
一旦找到第一个元素就停止枚举。至于
Contains
的使用,您需要考虑指定类型的引用是否等同于您正在执行的Id
比较。默认情况下不是这样。You should not even consider
Count
since you are only checking for the existence of a record. You should useAny
instead.Using
Count
forces to iterate the entire enumerable to get the correct count,Any
stops enumerating as soon as you found the first element.As for the use of
Contains
you need to take in consideration if for the specified type reference equality is equivalent to theId
comparison you are performing. Which by default it is not.假设 Record 正确实现了 GetHashCode 和 Equals,我会完全使用不同的方法:
基本上不需要进行 N * M 查找time - 上面的代码最终将根据其哈希码从
recs
构建一组记录,并且比原始代码更有效地查找不匹配项。如果您实际上还有更多要做的事情,您可以使用:(
我不太确定为什么您的原始代码使用
Single
从数据库中重新获取记录,而您已经将其作为<代码>记录...)Assuming
Record
implements bothGetHashCode
andEquals
properly, I'd use a different approach altogether:Basically there's no need to have an N * M lookup time - the above code will end up building a set of records from
recs
based on their hash code, and find non-matches rather more efficiently than the original code.If you've actually got more to do, you could use:
(I'm not quite sure why your original code is refetching the record from the database using
Single
when you've already got it asrec
...)Contains()
将对您的对象使用Equals()
。如果您没有重写此方法,Contains()
甚至可能返回不正确的结果。如果您已重写它以使用对象的Id
来确定身份,那么在这种情况下,Count()
和Contains()
几乎执行以下操作完全相同的事情。除了Contains()
一旦遇到匹配就会短路,而Count()
会继续计数。Any()
可能是比它们更好的选择。您确定这是您应用程序的瓶颈吗?对我来说,这感觉像是过早的优化。这是万恶之源,你知道的:)
Contains()
is going to useEquals()
against your objects. If you have not overridden this method, it's even possibleContains()
is returning incorrect results. If you have overridden it to use the object'sId
to determine identity, then in that caseCount()
andContains()
are almost doing the exact same thing. ExceptContains()
will short circuit as soon as it hits a match, where asCount()
will keep on counting.Any()
might be a better choice than both of them.Do you know for certain this is a bottleneck in your app? It feels like premature optimization to me. Which is the root of all evil, you know :)
由于可以保证有 1 个且只有 1 个,因此 Any 可能会更快。因为一旦它找到匹配的记录就会返回 true。
Count 将遍历整个列表,对每次出现的情况进行计数。因此,如果该项目在 1000 个项目列表中排名第一,它将检查这 1000 个项目中的每一个。
编辑
此外,这可能是一个值得提及的时候,不要进行过早的优化。
连接你的两种方法,在每个方法之前和之后放一个秒表。
创建一个足够大的列表(1000 个项目或更多,具体取决于您的域。)并查看哪个更快。
我的猜测是我们在这里谈论的是女士的顺序。
我完全支持编写高效的代码,只要确保您不会花费数小时来在每天调用两次的方法上节省 5 毫秒即可。
Since you're guarenteed that there will be 1 and only 1, Any might be faster. Because as soon as it finds a record that matches it will return true.
Count will traverse the entire list counting each occurrence. So if the item is #1 in the list of 1000 items, it's going to check each of the 1000.
EDIT
Also, this might be a time to mention not doing a premature optimization.
Wire up both your methods, put a stopwatch before and after each one.
Create a sufficiently large list (1000 items or more, depending on your domain.) And see which one is faster.
My guess is that we're talking on the order of ms here.
I'm all for writing efficient code, just make sure you're not taking hours to save 5 ms on a method that gets called twice a day.
事情会是这样:
It would be so:
我可以建议一种替代方法吗?我相信这种方法应该更快,因为即使在第一场比赛之后计数也会继续。
这样你就一定会在第一场比赛中中断,而不是继续计数。
May I suggest an alternative approach that should be faster I believe since count would continue even after the first match.
That way you are sure to break on the first match instead of continue to count.
如果需要知道元素的实际数量,请使用 Count();这是唯一的方法。如果要检查是否存在匹配记录,请使用 Any() 或 Contains()。两者都比 Count() 快得多,并且执行效果大致相同,但 Contains 将对整个对象进行相等性检查,而 Any() 将根据对象计算 lambda 谓词。
If you need to know the actual number of elements, use Count(); it's the only way. If you are checking for the existence of a matching record, use Any() or Contains(). Both are MUCH faster than Count(), and both will perform about the same, but Contains will do an equality check on the entire object while Any() will evaluate a lambda predicate based on the object.