如果.Count或.Count()在实现ICollection的对象上多次使用(因此具有O(1)计算复杂度,除非它已被覆盖),它是否在性能方面更好(不是内存方式) ,即使是一个非常小的差异,要将值缓存在临时变量中,而不是每次需要时访问属性值?
答案 0 :(得分:3)
是的,它可能(非常轻微)更快,因为方法调用的开销,相关的错误检查和(在Count()的情况下)ICollection的动态类型检查有一些开销。
虽然值得吗?这完全取决于您和您的应用程序。如果你处于一个非常紧密的内循环中,它可能是值得的。然后,在最近的.NET运行时,这种琐碎的属性可能会在这种情况下被内联。
与往常一样,让您的探查器告诉您应用程序中的热点位置。
答案 1 :(得分:3)
直接回答问题,即使是O(1)操作也需要很长时间才能完成;只是无论收集多大,它总是需要相同的时间。缓存结果并将其读回将会很快,但不能保证比任何给定的O(1)操作更快。你首先需要一些时间;)
答案 2 :(得分:2)
抱歉,我认为ICollection.Count
是O(1)
是错误的。它在道德上应该是,但不能保证它是:
public EvilCollection<T> : ICollection<T> {
private readonly ICollection<T> collection;
private readonly Func<int, int> slowGrowingFunction;
public EvilCollection(
ICollection<T> collection,
Func<int, int> slowGrowingFunction)
{
this.collection = collection;
this.slowGrowingFunction = slowGrowingFunction;
}
public int Count {
get {
Thread.Sleep(1000 * this.slowGrowingFunction(this.collection.Count));
return this.collection.Count;
}
}
// other methods wrap methods on collection for ICollection<T>
}
ICollection<T> evilCollection =
new EvilCollection<T>(collection, n => Ackermann(4, n));
哦不,evilCollection.Count
是O(Ackermann(4, n))
!
那就是说,我不会担心这个,除非我知道我可能会收到邪恶的收藏品,我发现这是一个重大的性能瓶颈。请记住,代码少了清楚,它可能不太正确(缓存结果后的计数更新是什么?)等。
只需编写最简单的代码(使用ICollection<T>.Count
)。当且仅当它是您应用程序中的性能瓶颈时,我会担心调整它。
答案 3 :(得分:0)
不,没有必要;使用临时变量没有任何好处。此外,如果您正在缓存计数,那么如果收集集发生变化,您将面临计数错误的风险。
答案 4 :(得分:0)
如果您确定.Count()
现在和该功能中将要执行的操作,则答案为否。答案是是如果.Count()
是某些可能发生变化的实施。假设你用一些可能不是O(1)的LinkedList来改变实现。