Стоимость доработки в .Net - PullRequest
5 голосов
/ 15 июня 2010

(1) Я прочитал много вопросов об IDisposable, где ответы рекомендуют не использовать Finalize, если вам не нужно из-за времени, затрачиваемого на процесс.
Чего я не видел, так это того, сколько стоит эта стоимость и как часто она оплачивается. Каждую миллисекунду? второй? час, день и т. д.

(2) Кроме того, мне кажется, что Finalize удобен, когда не всегда известно, можно ли избавиться от объекта. Например, класс шрифтов фреймворка. Элемент управления не может избавиться от него, потому что он не знает, является ли общий шрифт доступным. Шрифт обычно создается во время разработки, поэтому пользователь не будет знать, как его распорядиться, поэтому завершите его, чтобы окончательно избавиться от него, когда не останется ссылок. Это правильное впечатление?

Ответы [ 5 ]

7 голосов
/ 15 июня 2010

Основная проблема с finalize заключается в том, что он блокирует сборку мусора.Вместо этого вызывается финализатор, и объект собирается «при следующем запуске».Ну, технически IIRC финализатор запускает список объектов в отдельном потоке.Во всяком случае, это не проблема «каждую мс», а «несколько операций GC, необходимых для избавления от объектов».

4 голосов
/ 15 июня 2010

Finalize концептуально отличается от Dispose. Завершить можно только бесплатных неуправляемых ресурсов. Утилизация может освободить управляемые и неуправляемые ресурсы. Вы должны использовать каждый по мере необходимости. (Обратите внимание, что класс с Finalizer всегда должен реализовывать IDisposable).

Dispose должен вызываться явно; Finalize может быть вызван только GC.

Обновление: см. Мой блог в Как реализовать IDisposable и финализаторы: 3 простых правила .

1 голос
/ 15 июня 2010

Я отвечу на ваш второй вопрос.

Нет, Finalize не следует использовать таким образом. На самом деле, за исключением лишь нескольких незначительных случаев, вам следует переопределить Finalize (или объявить деструктор в C #), если класс напрямую содержит неуправляемые ресурсы.

Описанная вами проблема связана с правами собственности. Владелец класса IDisposable несет ответственность за срок его службы и решение о том, когда звонить Dispose. Другие части кода могут свободно использовать этот класс, но, поскольку они не могут претендовать на владение, они не должны участвовать в управлении временем жизни этого класса.

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

1 голос
/ 15 июня 2010
0 голосов
/ 15 июня 2010

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

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

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

Наказатель финализатора в основном состоит в том, что вы помещаете свой объект в очередь уровня 2, что требует больше времени для запуска.Если вы постоянно используете объекты, и они завершают работу, это может привести к тому, что коллекция уровня 2 будет запускаться чаще, чем просто для запуска потоков финализатора.

...