Подтвердить что ты не робот

Уничтожить объекты С# вручную

Я новичок в изучении С# (на основе Java и С++), и у меня есть вопрос об утилизации мусора вручную: можно ли даже вручную уничтожить объект на С#? Я знаю об интерфейсе IDisposable, но предположим, что я имею дело с классом, который я не писал, и он не реализует его? У него не было бы метода .Dispose(), поэтому и using { } отсутствует, а .Finalize всегда либо protected, либо private, чтобы не был и вариант.

(Я просто пытаюсь узнать, что возможно в С# в этом случае. Я полагаю, что если все остальное не удается, я могу наследовать гипотетический ImNotDisposable класс, чтобы он реализовал IDisposable.)

4b9b3361

Ответ 1

Вы не уничтожаете объекты .Net вручную. Вот что значит быть управляемой средой.

Фактически, если объект действительно достижим, то есть у вас есть ссылка, которую вы можете использовать, чтобы сообщить ГХ, какой объект вы хотите уничтожить, собирать этот объект будет невозможно. GC никогда не будет собирать объекты, которые все еще доступны.

То, что вы можете сделать, это вызвать GC.Collect() чтобы вызвать общую коллекцию. Тем не менее, это почти никогда не хорошая идея.

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

Последнее замечание об IDisposable. Вы должны использовать его только для типов, которые обертывают неуправляемые ресурсы: такие как сокеты, соединения с базой данных, объекты gdi и т.д. И случайная подписка на событие/делегат.

Ответ 2

Если объект недоступен, вы можете вызвать GC.Collect(), и объект будет уничтожен. Концепция IDisposable не имеет ничего общего с CLR и в основном используется для реализации кода пользователя для выполнения дополнительной логики удаления. Вызов Dispose() на объект не освободит объект от памяти, хотя он может очень хорошо распоряжаться любыми ресурсами, на которые ссылается этот объект.

Я должен добавить, что, хотя то, что я сказал, является способом достижения этого, в 99,9999% приложений вы никогда не должны звонить GC.Collect(), потому что это часто ухудшает производительность вашего приложения, а не улучшает его.

Ответ 3

Хотя вы можете запускать сборку мусора (вам нужно запустить GC для всех поколений, потому что вы не можете быть уверены в том, какое поколение имеет конечный объект) вы не можете принудительно завершить финализацию определенного объекта. Вы можете полагаться только на предположения о том, как работает сборщик мусора.

Furtnermore, так как финализация происходит по собственной теме, вы должны вызвать WaitForPendingFinalizers после запуска сбора мусора.

GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();

Как было отмечено другими, это может повредить производительности вашего приложения, потому что ненужное обращение к GC может способствовать тому, что в противном случае краткосрочные объекты будут более высокими поколениями, которые дороже собирать и собираются реже.

Вообще говоря, класс, реализующий финализатор (деструктор) и не реализующий IDisposable, неодобрительно. И все, что реализует IDisposable, должно вызывать его логику финализатора и подавлять себя от финализации при сборке мусора.

Недавно Джефф Рихтер опубликовал хороший трюк для получения уведомления при сборе мусора.

Еще одна замечательная статья о Основы сборщика мусора и рекомендации по производительности Рико Мариани (MSFT)

Ответ 4

Нет, вы не можете уничтожить определенный объект.

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

Ответ 5

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

Принудительная сборка мусора может быть выполнена с помощью GC.Collect, но не делайте этого. За 10 лет работы в качестве разработчика .NET я никогда не нуждался в этом.

Ответ 6

Невозможно уничтожить объект детерминированным способом. CLR определяет, когда помеченный объект восстанавливается. Это означает, что, хотя вы можете пометить объект для восстановления и убедиться, что управляемые и неуправляемые ресурсы убраны для удаления (путем реализации шаблона IDisposable), фактическое время освобождения памяти зависит от CLR. Это отличается от C++, где вы действительно можете удалить что-то, и тогда оно будет выпущено.

Ответ 7

Вы не можете вручную уничтожить объект "как С++ delete", все, что вы можете сделать, - это просто закрыть любые эксклюзивные ресурсы, которые приобрел объект, и обнулить все ссылки на этот объект, поэтому GC может собирать его, также не вызывать GC.Collect() самостоятельно, процесс GC является дорогостоящим, так как он должен приостанавливать все остальные потоки, чтобы безопасно собирать объекты из памяти, поэтому просто доверяйте GC, и он начнется при необходимости.

Ответ 8

Скажем, у вас есть матрица классов, и вы создали два матричных объекта aMatrix и bMatrix. В С# вы можете вручную уничтожить (завершить) объект следующим образом:

aMatrix = null;

GC.Collect();

Сборщик мусора заметит, что ваш aMatrix имеет значение null, и уничтожит (завершит) его. Является ли это хорошей идеей, это отдельная история.