首页 > 解决方案 > 是否可以跟踪类的当前实例数?

问题描述

在 .NET 中,我知道有一个垃圾收集器可以管理程序执行期间正在使用的内存。这意味着对象将在未使用时被清理。

我想知道是否可以在某个类中保留一个静态计数器,当该类的实例被创建或垃圾收集时自动更新。例如,如果我创建了某个CountableInstance类的一些实例,那么它们每个都可以有一个根据创建时间InstanceIndex跟踪它们当前位置的实例。

这样的流程可能如下所示:

  1. 程序开始
  2. CountableInstance ctble0是用InstanceIndex == 0
  3. CountableInstance ctble1是用InstanceIndex == 1
  4. CountableInstance ctble2是用InstanceIndex == 2
  5. CountableInstance ctble1未使用并收集垃圾
  1. 节目结束

我猜想跟踪CountableInstance实例的数量会是这样的:

public class CountableInstance
{
    public static int total = 0;
    public CountableInstance()
    {
        InstanceIndex = total;
        total++; // Next instance will have an increased InstanceIndex
    }
    public CountableInstance(...) : this()
    {
        // Constructor logic goes here
    }

    public int InstanceIndex { get; private set; }
}

这会处理有多少实例,并且还会为每个新对象分配正确的索引。然而,这个实现错过了当实例被垃圾收集时应该发生的逻辑。

如果可能,我该如何实施?跟踪使用特定接口的对象的实例是否也有效?

标签: c#class.net-corestatic

解决方案


您可以实现以下要点,但这似乎是 IMO 的一个坏主意;尤其是:

  1. 终结器不是免费的(也不是IDisposable.Dispose()
  2. 您可以在不运行构造函数的情况下创建对象(如果您足够努力的话)

无论如何,代码:

public class CountableInstance
{
    static int s_Total, s_Alive;
    public CountableInstance() {
        // need a separate total vs alive so we don't give duplicate
        // InstanceIndex, at least for the first 4 billion objects
        InstanceIndex = Interlocked.Increment(ref s_Total);
        Interlocked.Increment(ref s_Alive);
    }
    ~CountableInstance() {
        Interlocked.Decrement(ref s_Alive);
    }
    public int InstanceIndex { get; }
    public static int Alive => Volatile.Read(ref s_Alive);
    public static int Total => Volatile.Read(ref s_Total);
}

推荐阅读