Если я правильно понимаю, среда выполнения .net всегда будет убирать за мной. Поэтому, если я создаю новые объекты и перестаю ссылаться на них в своем коде, среда выполнения очистит эти объекты и освободит память, которую они занимали.
Если это так, то зачем тогда некоторым объектам нужен деструктор или метод dispose? Разве время выполнения не очистит их, когда на них больше не будут ссылаться?
Финализаторы нужны для того, чтобы гарантировать возврат в систему дефицитных ресурсов, таких как файловые хэндлы, сокеты, объекты ядра и т. д. Поскольку финализатор всегда запускается в конце жизни объекта, он является назначенным местом для освобождения этих хэндлов.
Шаблон Dispose
используется для обеспечения детерминированного уничтожения ресурсов. Поскольку сборщик мусора во время выполнения .net является недетерминированным (это означает, что вы никогда не можете быть уверены в том, когда время выполнения соберет старые объекты и вызовет их финализатор), был необходим метод для обеспечения детерминированного освобождения системных ресурсов. Поэтому, когда вы правильно реализуете паттерн Dispose
, вы обеспечиваете детерминированное освобождение ресурсов, а в случаях, когда потребитель небрежен и не утилизирует объект, финализатор очистит объект.
Простым примером того, зачем нужен Dispose
, может быть метод быстрого и грязного журнала:
public void Log(string line)
{
var sw = new StreamWriter(File.Open(
"LogFile.log", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None));
sw.WriteLine(line);
// Since we don't close the stream the FileStream finalizer will do that for
// us but we don't know when that will be and until then the file is locked.
}
В приведенном выше примере файл будет оставаться заблокированным до тех пор, пока сборщик мусора не вызовет финализатор на объекте StreamWriter
. Это создает проблему, поскольку в это время метод может быть вызван снова для записи журнала, но на этот раз он потерпит неудачу, поскольку файл все еще заблокирован.
Правильным способом является утилизация объекта после завершения его использования:
public void Log(string line)
{
using (var sw = new StreamWriter(File.Open(
"LogFile.log", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))) {
sw.WriteLine(line);
}
// Since we use the using block (which conveniently calls Dispose() for us)
// the file well be closed at this point.
}
BTW, технически финализаторы и деструкторы означают одно и то же; я предпочитаю называть деструкторы c# 'финализаторами', поскольку иначе они склонны путать людей с деструкторами C++, которые, в отличие от C#, являются детерминированными.
Предыдущие ответы хороши, но позвольте мне подчеркнуть важный момент здесь еще раз. В частности, вы сказали, что
если я правильно понял .объем выполнения всегда будет убирать после меня.
Это только отчасти правильно. В самом деле, .Чистая только предлагает автоматическое управление для одного конкретного ресурса: основной памяти. Все остальные ресурсы необходимость ручной чистки.<суп>1)</SUP и ГТ;
Как ни странно, основную память получает особый статус в почти всех дискуссиях о программе ресурсов. Там's, конечно, хорошая причина для этого – основная память-это часто самый дефицитный ресурс. Но это's стоит помнить, что существуют и другие типы ресурсов, которые также нуждаются в управлении.
<суп>1)</SUP-серфинг> обычная попытка решения состоит в жизни другие ресурсы для жизни местах памяти или идентификаторов в коде – следовательно, существование финализаторы.
Сборщик мусора будет работать только если система не находится под давлением памяти, если она действительно нуждается, чтобы освободить некоторый объем памяти. Это значит, вы никогда не можете быть уверены, когда сборщик мусора будет работать.
Теперь, представьте, что вы являетесь подключения к базе данных. Если вы позволите ГК убирать за вами, вы можете быть подключены к базе данных для намного дольше, чем нужно, вызывая странные ситуации нагрузки. В этом случае, вы хотите реализовать IDisposable, так что пользователь может вызвать Dispose() или использовать используя (), чтобы действительно убедиться, что соединение закрыто как можно скорее, не полагаясь на ГК, которые могут работать значительно позже.
В целом, интерфейс IDisposable реализуется на любой класс, который работает с неуправляемыми ресурсами.
Реальная причина в том, что .чистая сборка мусора не предназначены для сбора неуправляемые ресурсы поэтому очистка этих ресурсов по-прежнему находится в руках разработчика. Кроме того, объект финализаторы не вызывается автоматически, когда объект выходит из области видимости. Они называются ГК в какой-то неопределенное время. И когда они вам звонили, ГК не'т запустить его прямо сейчас, он ждет следующего раунда, чтобы назвать это, увеличивая время, чтобы очистить еще больше, не хорошо, когда ваши объекты несут скудные неуправляемые ресурсы (например, файлы или сетевые подключения). Введите одноразовый шаблон, где разработчик может вручную освободить дефицитные ресурсы в определенное время (при звонке yourobject.Метод Dispose() или с помощью(...) заявление). Помните, что вы должны вызова GC.SuppressFinalize(этого); в метод Dispose, чтобы рассказать ГХ, что объект вручную утилизируются и должны'т быть завершена. Я предлагаю вам взглянуть на схему руководство книги К. Cwalina и Б. Абрамс. Это объясняет одноразовые модели очень хорошие.
Удачи!
Простое объяснение:
Некоторые рекомендации по реализации метода finalize:
Некоторые рекомендации по реализации метода Dispose:
Объекты, которым нужны деструкторы и методы утилизации, используют неуправляемые ресурсы. Поэтому сборщик мусора не может очистить эти ресурсы, и вам придется делать это самостоятельно.
Посмотрите документацию MSDN по IDisposable; http://msdn.microsoft.com/en-us/library/system.idisposable.aspx.
В примере используется неуправляемый обработчик - IntPr.
Есть несколько (очень мало) случаев, когда это может быть необходимо, чтобы выполнить определенное действие, когда чисто управляемый объект больше не используется, я могу'т придумать пример с верхней части моей головы, но я видел пару законное использование на протяжении многих лет. Но главная причина-для очистки неуправляемых ресурсов, что объект может быть используя.
Так, в общем, вы выиграли'т должны использовать метод Dispose/доработать шаблон, если вы используете неуправляемые ресурсы.
Главным образом для non-управляемого кода и взаимодействия с управляемым кодом. на "чисто" и управляемый код не нужен финализатор. Одноразовые с другой стороны-это просто удобный шаблон, чтобы заставить что-то будет выпущен, когда вы сделали с ним.
Интернет .Чистая сборщик мусора знает, как справиться с управляемыми объектами .Net во время выполнения. Но шаблон Dispose (интерфейс IDisposable) используется в первую очередь для ООН-управляемые объекты, используя приложение.
Иными словами,.Net для выполнения не'т должен знать, как справиться с каждым типом устройства или ручки там (закрытия сетевых подключений, дескрипторы файлов, графические приборы и т. д.), Поэтому использование IDisposable, который предоставляет возможность сказать: "Дайте мне реализовать некоторые очистки моей" В тип. Видя, что реализация, сборщик мусора может вызвать Dispose() и убедитесь, что вещи за пределами управляемой куче очищаются.
Некоторые объекты могут нуждаться в очистке низкоуровневых элементов. Например, оборудование, которое необходимо закрыть, и т.д.
Потому что сборщик мусора не может собрать то, что контролируемую среду не выделяет. Поэтому любой вызов неуправляемого API, который приводит к выделению памяти должна быть собрана в старинке.