Per Reflection wird das nicht gehen, weil man dadurch nicht auf die
internen Strukturen der CLR zugreifen kann, diese sind opak. Es können
im Prinzip nur Typinformationen abgefragt und dynamischer Code
ausgeführt werden.
Man kann es natürlich mit einer Liste machen, nur hat man dann
allerdings das Problem, dass wenn man eine Instanz nach der Verwendung
nicht wieder explizit aus der Liste entfernt durch die Objektreferenz
ein Speicherleck entsteht - denn solange das Objekt von der Liste
referenziert wird, kann es nicht vom GC bereinigt werden, auch wenn es
schon lange nicht mehr benutzt wird. Eine Möglichkeit wäre, IDisposable
zu implementieren und in der Dispose()-Methode die Instanz explizit
wieder aus der Liste zu entfernen, aber auch das ist problematisch weil
der Dispose-Aufruf nicht garantiert werden kann (wenn man z.B. keinen
using-Block verwendet und den Aufruf vergisst) oder man nicht weiß, ob
das Objekt an anderer Stelle noch benötigt wird. Höchstens per
Destruktor (Finalizer), was sich allerdings negativ auf die Performance
auswirken kann.
Das reine Zählen, wie viele Instanzen eines Objektes erstellt wurden,
wäre noch relativ simpel über einen Zähler in einem statischen Feld, der
im Konstruktor inkrementiert wird, zu lösen. Mit dem
[ThreadStatic]-Attribut wahlweise auch per Thread.
Wenn man schon eine Liste nimmt, dann bitte mit schwachen Referenzen (so
genannte "Weak List"). Generell sollte man solche Konstrukte eher meiden
und versuchen die behandelte Problematik anders zu lösen. Vor allem in
Multi-Thread-Szenarien. Threadübergreifende Objekte, sofern nicht
immutable, sind immer schwierig zu handhaben. Und List<T> ist auch nicht
threadsicher!