Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is is possible to keep track of the current number of instances of a class?

In .NET, I understand that there is a garbage collector that will manage the memory that's being used during the execution of a program. This means that objects will be cleaned up when they go unused.

I was wondering if I could keep a static counter in a certain class that automatically updates when instances of that class are created or garbage collected. For example, if I create some instances of some CountableInstance class, then they could each have an InstanceIndex that keeps track of their current position based on when they were created.

Such a flow could look like this:

  1. Program starts
  2. CountableInstance ctble0 is created with InstanceIndex == 0
  3. CountableInstance ctble1 is created with InstanceIndex == 1
  4. CountableInstance ctble2 is created with InstanceIndex == 2
  5. CountableInstance ctble1 goes unused and gets garbage collected
  • ctble0's index stays the same
  • ctble2's index becomes 1
  1. Program ends

I'm guessing that keeping track of the number of CountableInstance instances would look like this:

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; }
}

This takes care of how many instances there are and it also assigns the correct index to each new object. However, this implementation misses the logic that should happen when an instance is garbage collected.

If possible, how could I implement it? Would it also work to keep track of instances of objects that use a particular interface?

like image 274
JansthcirlU Avatar asked Oct 14 '20 11:10

JansthcirlU


2 Answers

You can achieve the gist of this as below, but this seems like a bad idea IMO; in particular:

  1. finalizers aren't free (and neither is IDisposable.Dispose())
  2. you can create objects without ever running a constructor (if you try hard enough)

Anyway, code:

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);
}
like image 138
Marc Gravell Avatar answered Sep 30 '22 19:09

Marc Gravell


you could do something like this:

public class CountableInstance : IDisposable
{
    public static int total = 0;
    ...




    public void Dispose()
    {
         //total--;
         //Edit:
         Interlocked.Decrement(total);
    }

}

this would keep track of what happens within your application. but as far as i know garbage collection could still be delayed to a later point long after Dispose.

like image 31
Paul Pascher Avatar answered Sep 30 '22 21:09

Paul Pascher