9

我不想在微优化上引发一场激烈的战争,但我对某些事情感到好奇。

创建没有内在数据的类型的实例在内存和性能方面的开销是多少?

例如,一个实现的简单类IComparer<T>可能只包含一个Compare方法,而没有属性或字段。

class FooComprarer : IComparer<Foo>
{
    public int Compare (Foo x, Foo y) 
    {
        // blah, blah
    }
}

我见过的典型示例代码只是调用new FooComparer(),只要需要其中之一。

我无法想象这里的实例化成本非常高,但我很想知道它实际上是什么。以及它将如何与一个静态工厂类进行比较,该类维护一个比较器类型的字典,以便一个比较器实例可以在需要的任何地方使用。

4

3 回答 3

13

有一些开销,但与您将使用比较器的目的相比,它可能可以忽略不计。

在 32 位和 64 位系统上,该实例将使用 16 字节的堆空间。开销是两个指针,在 32 位系统上使用 8 个字节,在 64 位系统上使用 16 个字节。但是 32 位系统中的内存管理器不能分配小于 16 字节的块,所以块中会有 8 个未使用的字节。

如果您经常重复使用这些比较器,您可能会考虑保留它们。但是,您还应该考虑到短寿命对象对内存管理造成的压力比长寿命对象要小得多,因此您必须大量重用比较器,以使它们保持活力是值得的。

于 2011-06-27T23:52:31.963 回答
2

至少,即使类对象没有数据成员,它仍将具有指向其类型信息和一些内务信息的指针。

根据http://www.simple-talk.com/dotnet/.net-framework/object-overhead-the-hidden-.net-memory--allocation-cost/

在 32 位系统上,每个对象都有一个 8 字节的标头 [...] 在 64 位系统上,情况更糟。对象头增加到 16 个字节。

于 2011-06-27T23:40:12.040 回答
2

这仅与您的问题相关,但如果您使用 C# 3.0 或更高版本,则可以使用此模式:

public class AdhocComparer<T> : IComparer
{
    Func<T, T, int> comparer;

    AdhocComparer(Func<T, T, int> comparer)
    {

        this.comparer = comparer;

    }

    public int Compare (Foo x, Foo y) 
    {
        return comparer(x, y);
    }

}

并像这样使用:

var fooComparer = new AdhocComparer<Foo>( (x, y) => /* do stuff */);

这样您就不必为您需要的每种 IComparer 创建一个类。

于 2011-06-28T02:04:56.537 回答