views:

2079

answers:

4

How can I count the number of objects of a class type within a method of that class? For that matter, how to do it outside of a class without adding the objects to a list?

I should have thought of that! Thanks! I'm gonna leave it unanswered for a little while to see if there is a better way, because I agree. I'm just sortv wrapping my head around OO. If you don't mind let me explain a little more and maybe there is a better way in general?

I have an object class that i want to add 3 pieces of information to, but first I want to cycle through and make sure there are no other objects with any of the three pieces the same, and if there are, do something different for each case.

A: 

You could implement some type of reference counting scheme, though I am not sure why you would want to do this. For every call to 'new' you can increment a counter, and you could then define a finalizer to decrement this value. There is probably a better, more robust way to do it, this was just off the top of my head.

Ed Swangren
+1  A: 

I'm not exactly sure what you mean. But it might be this:

MethodInfo methodInfo = ...;
MethodBody body = methodInfo.GetMethodBody();
int count = body.LocalVariables.Count(variable => variable.LocalType == typeof(DesiredType));

Another possibility: The profiler in Team Suite (and maybe others) can tell you:

  • The number of objects of type T allocated in every method
  • The number of bytes allocated in each method

Edit: Due to the lack of a "dup n" or "swap n, n+1" IL instruction, the compiler is forced to generate locals you might not expect (ones you didn't explicitly declare). The compiler is also free to remove locals where possible when optimization is on.

280Z28
That's counting the number of variables, not the number of instances of the class...
Adam Robinson
@Adam: When the post is at all ambiguous, you have to guess some things. That's why I prefixed it with "I'm not exactly sure what you mean." It's correct for counting the number of local variables, which is either an answer to the OP or a hint to reword things. It's not "simply incorrect."
280Z28
A: 

Do you mean in a way that would allow you to track how many times you had called new MyClass() such that there are N instances taking up memory at the moment, and you want to know the value of N?

If you want to track memory usage, use the debugger to dump the state of the heap. The thing is, the answer will depend on the GC and whether it has collected unreferenced objects.

You could have a counter you increment in the constructor, but when to decrement it? Finalizers run in another thread, which underlines the unpredictability of this whole idea. Might be better to implement IDisposable to decrement the counter, and require the objects to be Disposed when not needed.

Daniel Earwicker
+4  A: 

The only way to accomplish what you're looking for is to keep a static list of these objects in the class itself. If you just want to see if there is an instance somewhere that hasn't been garbage collected, then you'll want to use the WeakReference class. For example...

public class MyClass
{
    private static List<WeakReference> instances = new List<WeakReference>();

    public MyClass()
    {
         instances.Add(new WeakReference(this));
    }

    public static IList<MyClass> GetInstances()
    {
        List<MyClass> realInstances = new List<MyClass>();
        List<WeakReference> toDelete = new List<WeakReference>();

        foreach(WeakReference reference in instances)
        {
            if(reference.IsAlive)
            {
                realInstances.Add((MyClass)reference.Target);
            }
            else
            {
                toDelete.Add(reference);
            }
        }

        foreach(WeakReference reference in toDelete) instances.Remove(reference);

        return realInstances;
    }
}

Since you're new to OO/.NET, don't let the WeakReference use scare you. The way garbage collection works is by reference counting. As long as some piece of code or an object has access to a particular instance (meaning it's within scope as a or as part of a local, instance, or static variable) then that object is considered alive. Once that variable falls OUT of scope, at some point after that the garbage collector can/will collect it. However, if you were to maintain a list of all references, they would never fall out of scope since they would exist as references in that list. The WeakReference is a special class allows you to maintain a reference to an object that the garbage collector will ignore. The IsAlive property indicates whether or not the WeakReference is pointing to a valid object that still exists.

So what we do here is keep this list of WeakReferences that point to every instance of MyClass that's been created. When you want to obtain a list of them, we iterate through our WeakReferences and snatch out all of them that are alive. Any we find that are no longer alive are placed into another temporary list so that we can delete them from our outer list (so that the WeakReference class itself can be collected and our list doesn't grow huge without reason).

Adam Robinson