Когда я должен размещать свои объекты в .NET?

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

Ответ 1

Утилизируйте объект в тот момент, когда вы закончите с ним. Одноразовые объекты представляют объекты, содержащие ценный ресурс, о котором CLR не знает об этом. Следовательно, GC также не знает о ресурсах и не может принять разумные решения относительно того, когда он должен собрать одноразовый объект и, следовательно, освободить базовый ресурс.

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

Быстрый пример того, как это может произойти. Давайте рассмотрим базовый ресурс как дескриптор Win32. Они очень конечны и довольно малы. Вы запускаете операцию, которая создает много объектов Foo. Объекты Foo реализуют IDisposable и несут ответственность за создание и удаление дескриптора Win32. Они не освобождаются вручную, а при различии причудливо превращаются в кучу Gen2. Эта куча освобождается довольно редко. Со временем достаточно экземпляров Foo превратить их в кучу Gen2, чтобы взять все доступные ручки. Поэтому новые объекты Foo не могут быть созданы независимо от того, сколько памяти используется.

Фактически, чтобы освободить ручки, потребуется выделить довольно большой объем памяти в течение одной операции, чтобы дать достаточное давление, чтобы освободить экземпляры.

Ответ 2

Если объект реализует IDisposable, вы должны избавиться от него, как только вы закончите с ним. Самый простой способ - окружить его с помощью блока:

using (SqlCommand cmd = new SqlCommand(conn)) {
    cmd.ExecuteNonQuery();
}

Ответ 3

Причина, по которой вы всегда должны вызывать Dispose() для любого типа, реализующего IDisposable, заключается в том, что обычно используется для обозначения того, что тип приобретает неуправляемые ресурсы. Особенно важно, чтобы они были освобождены и как можно раньше. Как говорили другие, using - предпочтительный способ сделать это.

Ответ 4

Есть несколько способов взглянуть на это. Один из способов пытается выяснить, действительно ли нужно избавляться от объекта, как только он больше не нужен, например, используя Reflector, чтобы увидеть, действительно ли он держится за неуправляемые ресурсы или если они случайно удалены в любом случае. Другая перспектива заключается в том, чтобы предположить, что если объект реализует IDisposable, вам не нужно определять, действительно ли Dispose() нужно вызвать - вы всегда вызываете его. Я думаю, что это правильный путь. Заглядывая в частную реализацию объектов, чтобы принимать решения о том, как вы должны их потреблять, увеличивается риск связанного с реализацией, которая может измениться. Например, LINQ to SQL DataContext. Он реализует IDispose, но в основном очищает после себя без необходимости явного вызова Dispose(). Мое предпочтение состоит в том, чтобы написать код, который явно располагает, но другие предложили его не нужно.

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

И как сказано ранее, использование (..) {...} является вашим другом для разработчиков IDisposable.

Ответ 5

Если объект реализован как IDisposable, вполне вероятно, что он удерживает неуправляемые ресурсы. Таким образом, эмпирическое правило состоит в том, чтобы вызвать Dispose в тот момент, когда вы закончите с объектом, либо напрямую, либо с помощью используемого блока. Не полагайтесь на GC, так как это означает, что IDisposable предназначен для детерминированного выпуска ресурсов.

Ответ 6

В большинстве случаев полагается на GC 'works'. Классическое исключение - когда у вас тяжелое взаимодействие ресурсов - в этом случае лучше всего использовать explicilty.

очевидно, например.

using (var conn = new SqlConnection(connString)) {}

"Использование" блоков - это, безусловно, самый чистый и самый надежный способ обеспечения правильного удаления объектов. "Использование" блоков можно использовать с любыми объектами, которые реализуют IDisposable.

Ответ 7

Нет, вы можете уйти с вызовом Dispose в случаях, когда вы не используете неуправляемый ресурс. Но если ваш класс держит неуправляемый ресурс, скажем, временный файл, который нужно удалить, тогда вам придется явно вызвать Dispose.

Вы можете избежать вызова Dispose, написав код освобождения в методе Finalize, но тогда вы зависите от сборщика мусора, потому что вы никогда не уверены, что когда сборщик мусора завершит ваш объект. Чтобы быть в безопасности, если вы разрабатываете такой класс, который содержит неуправляемый ресурс, вы можете написать тот же код для освобождения объектов как в методе Dispose And Finalize, но если вы это сделаете, всегда используйте SuppressFinalize() в вашем методе удаления потому что это предотвратит вызов метода Finalize(), если ваш объект уже находится в очереди завершения.

Ответ 8

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