Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当操作为O(1)时,是否值得缓存.Count(或.Count())的结果?_C#_.net_Performance_Count - Fatal编程技术网

C# 当操作为O(1)时,是否值得缓存.Count(或.Count())的结果?

C# 当操作为O(1)时,是否值得缓存.Count(或.Count())的结果?,c#,.net,performance,count,C#,.net,Performance,Count,如果在实现ICollection的对象上多次使用.Count或.Count()(因此计算复杂度为O(1),除非它被重写),那么它的性能是否更好(而不是内存方面),哪怕只是很小的差异,要将值缓存在临时变量中,而不是每次需要时都访问属性值?否,不需要;使用临时变量没有任何好处。此外,如果正在缓存计数,则如果集合集发生更改,则可能会导致计数不正确。如果您确定.count()现在和在功能中要执行的操作,则答案是否。答案是是如果。Count()是一些可能更改的实现。假设您使用一些可能不是O(1)的Link

如果在实现ICollection的对象上多次使用.Count或.Count()(因此计算复杂度为O(1),除非它被重写),那么它的性能是否更好(而不是内存方面),哪怕只是很小的差异,要将值缓存在临时变量中,而不是每次需要时都访问属性值?

否,不需要;使用临时变量没有任何好处。此外,如果正在缓存计数,则如果集合集发生更改,则可能会导致计数不正确。

如果您确定
.count()
现在和在功能中要执行的操作,则答案是否。答案是如果
。Count()
是一些可能更改的实现。假设您使用一些可能不是O(1)的LinkedList更改了实现

是的,它可能会(稍微)快一些,因为方法调用的开销、关联的错误检查以及(在Count()的情况下)ICollection的动态类型检查都有一定的开销

但是值得吗?这完全取决于你和你的申请。如果你处于一个非常紧密的内部循环中,这可能是值得的。然后,在最近的.NET运行时上,这种琐碎的属性在这种情况下可能会被内联


一如既往,让您的探查器告诉您应用程序中的热点在哪里。

对不起,认为
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));
public集合:ICollection{
私有只读ICollection集合;
私有只读函数slowgrowing函数;
公众藏品(
i收集,
函数(慢行函数)
{
this.collection=collection;
this.slowGrowingFunction=slowGrowingFunction;
}
公共整数计数{
得到{
Sleep(1000*this.slowgrowing函数(this.collection.Count));
返回此.collection.Count;
}
}
//其他方法在ICollection的集合上包装方法
}
ICollection集合=
新集合(集合,n=>Ackermann(4,n));
哦,不,
evilCollection.Count
O(阿克曼(4,n))

也就是说,除非我知道我可能会进入邪恶的集合,否则我不会担心这个问题,我发现这是一个严重的性能瓶颈。请记住,代码不太清晰,可能不太正确(缓存结果后的计数更新是多少?),等等


只需编写最简单的代码即可(使用
ICollection.Count
)。如果且仅当它是应用程序中的性能瓶颈时,我才会担心如何调整它。

直接回答这个问题,即使是O(1)操作也可能需要很长时间才能完成;只是不管收藏量有多大,都需要相同的时间。缓存结果并将其读回总是很快的,但不能保证比任何给定的O(1)操作都快。你首先需要一些时间;)

这是一个修辞问题还是某种哲学问题?前传:@Jason-是的,你可以,这就是为什么我说“几乎总是”。但那将是一个写得非常糟糕的类,表现非常糟糕,所以你可能不会。@Jason-你完全错了。一个人可以在代码中做很多坏事。这并不意味着有人会这样做,即使有人这样做了,他们的代码也会因为工作不好而被丢弃。@Jason:“如果我能为每一个不是邪恶的人创造一个邪恶的,那么邪恶的人至少和不邪恶的人一样多。”这句话意味着你有能力编写糟糕的代码,意味着坏的集合至少和好的集合一样多,这是完全错误的。大多数程序员永远不会写这样的邪恶的集合,即使你也不会。至少我希望如此!因此,你认为存在的邪恶收藏和美好收藏一样多的说法是完全错误的。任何人都不应该写这样的收藏。你甚至承认这是邪恶的。您每次必须计数的集合将正确定义为可枚举的集合,而不是集合或列表。您没有抓住要点。假设
ICollection.Count
O(1)
,这是错误的。这是错误的,因为我可以举一个不正确的例子。这不是唯一的例子(这太离谱了),甚至可能有真实世界的例子。但是,如果您正在对接口
ICollection
进行编码,那么您不知道会发生什么。您不知道这是一个
集合
,还是另一个使
i集合。Count
不是
O(1)
。因此,你不能全盘假设,
ICollection.Count
O(1)
,然后从这个错误的假设开始胡闹。杰森,是的,你可以这样假设。所有代码都需要运行和测试。当您的邪恶集合表现不佳时(不仅在OP的使用中,而且在许多常见用途中),它将被丢弃或进行防御编码,例如通过编写一个正确缓存计数的包装器类。@AresAvatar:您不能这样假设。这是我的方法。我是一个API作者,或者是一个框架作者,或者谁知道呢。在我的API中,我提供了这个方法:
publicvoidm(ICollection集合)
我不知道
collection
将是什么。没有一个我不能在我的方法
M
中假设
collection.Count
O(1)
。我不能,因为我不知道运行时的
集合是什么。你不明白吗?我认为你在这件事上是错的,我认为我们不会同意。我不作进一步评论。