Краткий ответ: если у вас нет неуправляемых ресурсов (файловых дескрипторов и т. Д.), Вам не о чем беспокоиться.
Длинный ответ немного сложнее.
Когда .NET решает освободить часть памяти, он запускает сборщик мусора . Это ищет все объекты, которые все еще используются, и помечает их как таковые. Любая локальная переменная (в любом стековом фрейме любого потока), которая все еще может быть прочитана, считается как root , как и статические переменные. (На самом деле я считаю, что на статические переменные ссылаются с помощью живых объектов Type, на которые ссылаются с помощью живых объектов AppDomain, но по большей части вы можете рассматривать статические переменные как корни.)
Сборщик мусора просматривает каждый объект, на который ссылается корень, а затем находит больше «живых» ссылок на основе переменных экземпляра в этих объектах. Он повторяется, находя и помечая все больше и больше объектов как «живых». После завершения этого процесса он может просмотреть все остальные объектов и освободить их.
Это очень широкая концептуальная картина - но она становится намного более подробной, когда вы думаете о поколенческой модели сборки мусора, финализаторов, параллельной сборки и т. Д. Я настоятельно рекомендую вам прочитать * 1017 Джеффа Рихтера * CLR через C # , который подробно описан в этом. У него также есть статья two part (начиная с 2000 года, но все еще очень актуальная), если вы не хотите покупать книгу.
Конечно, все это не означает, что вам не нужно беспокоиться об использовании памяти и времени жизни объектов в .NET. В частности:
- Создание объектов бессмысленно будет стоить производительности. В частности, сборщик мусора работает быстро, но не бесплатно. Ищите простых способов уменьшить использование памяти при кодировании, но микрооптимизация до того, как вы поймете, что у вас есть проблема, тоже плохо.
- Возможно «утечка» памяти, делая объекты доступными дольше, чем вы предполагали. Две достаточно распространенные причины этого - статические переменные и подписки на события. (Подписка на событие делает обработчик событий доступным от издателя событий, но не наоборот.)
- Если вы используете больше памяти (живым, доступным способом), чем у вас есть, ваше приложение вылетит. .NET не может многое сделать, чтобы предотвратить это!
- Объекты, которые используют ресурсы вне памяти, обычно реализуют
IDisposable
. Вы должны вызвать Dispose
для них, чтобы освободить эти ресурсы, когда вы закончите с объектом. Обратите внимание, что не не освобождает сам объект - это может сделать только сборщик мусора. Оператор using
в C # является наиболее удобным способом надежного вызова Dispose
даже при наличии исключения.