Подсчитать количество объектов типа класса в методе класса

Как я могу подсчитать количество объектов типа класса в методе этого класса? Если на то пошло, как это сделать вне класса, не добавляя объекты в список?

Я должен был подумать об этом! Спасибо! Я оставлю это без ответа на некоторое время, чтобы посмотреть, есть ли лучший способ, потому что я согласен. Я просто сортирую голову вокруг OO. Если вы не возражаете, позвольте мне объяснить немного больше и, может быть, есть лучший способ в целом?

У меня есть класс объектов, в который я хочу добавить 3 части информации, но сначала я хочу пройтись по ним и убедиться, что нет других объектов с любой из трех одинаковых частей, и если они есть, что-то сделать разные для каждого случая.


person Nona Urbiz    schedule 22.07.2009    source источник


Ответы (4)


Единственный способ выполнить то, что вы ищете, - это сохранить статический список этих объектов в самом классе. Если вы просто хотите посмотреть, есть ли где-то экземпляр, который не был собран мусором, вам нужно использовать класс WeakReference. Например...

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

Поскольку вы новичок в OO/.NET, пусть вас не пугает использование WeakReference. Работа сборки мусора основана на подсчете ссылок. Пока какой-то фрагмент кода или объект имеет доступ к конкретному экземпляру (то есть находится в области видимости как локальная, экземплярная или статическая переменная или как часть), этот объект считается живым. Как только эта переменная выйдет из области видимости, в какой-то момент после этого сборщик мусора сможет/соберет ее. Однако, если бы вы поддерживали список всех ссылок, они никогда не выпадали бы из области действия, поскольку существовали бы как ссылки в этом списке. WeakReference — это специальный класс, позволяющий вам поддерживать ссылку на объект, который сборщик мусора будет игнорировать. Свойство IsAlive указывает, указывает ли WeakReference на допустимый объект, который все еще существует.

Итак, что мы здесь делаем, так это сохраняем этот список WeakReference, указывающих на каждый экземпляр MyClass, который был создан. Когда вы хотите получить их список, мы перебираем наши WeakReference и выхватываем все живые. Все, кого мы находим, которые больше не существуют, помещаются в другой временный список, чтобы мы могли удалить их из нашего внешнего списка (чтобы можно было собрать сам класс WeakReference, и наш список не разрастался без причины).

person Adam Robinson    schedule 22.07.2009

Я не совсем уверен, что вы имеете в виду. Но может быть это:

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

Другая возможность: профилировщик в Team Suite (и, возможно, другие) может сказать вам:

  • Количество объектов типа T, выделенных в каждом методе
  • Количество байтов, выделенных в каждом методе.

Изменить: из-за отсутствия IL-инструкции "dup n" или "swap n, n+1" компилятор вынужден генерировать локальные переменные, которых вы, возможно, не ожидаете (те, которые вы явно не объявляли ). Компилятор также может удалять локальные переменные, когда это возможно, когда оптимизация включена.

person Sam Harwell    schedule 22.07.2009
comment
Это подсчет количества переменных, а не количество экземпляров класса... - person Adam Robinson; 23.07.2009
comment
@Adam: Когда сообщение вообще двусмысленно, вы должны догадаться о некоторых вещах. Вот почему я поставил перед ним префикс «Я не совсем уверен, что вы имеете в виду». Это правильно для подсчета количества локальных переменных, что является либо ответом на ОП, либо намеком на переформулировку. Это не просто неправильно. - person Sam Harwell; 23.07.2009

Вы можете реализовать какую-то схему подсчета ссылок, хотя я не уверен, зачем вам это нужно. Для каждого вызова «нового» вы можете увеличивать счетчик, а затем вы можете определить финализатор для уменьшения этого значения. Вероятно, есть лучший и более надежный способ сделать это, это просто пришло мне в голову.

person Ed S.    schedule 22.07.2009

Вы имеете в виду способ, который позволил бы вам отслеживать, сколько раз вы вызывали new MyClass(), чтобы в данный момент память занимали N экземпляров, и вы хотите знать значение N?

Если вы хотите отслеживать использование памяти, используйте отладчик для создания дампа состояния кучи. Дело в том, что ответ будет зависеть от сборщика мусора и от того, собрал ли он нереференсные объекты.

У вас может быть счетчик, который вы увеличиваете в конструкторе, но когда его уменьшать? Финализаторы запускаются в другом потоке, что подчеркивает непредсказуемость всей этой идеи. Возможно, лучше реализовать IDisposable для уменьшения счетчика и требовать, чтобы объекты удалялись, когда они не нужны.

person Daniel Earwicker    schedule 22.07.2009