IDisposable, Финализаторы и определение неуправляемого ресурса

Если вы действительно хотите сделать вкладки красивыми и короткими, посмотрите на Clearlooks Compact .

Я предпочел просто ударить по всей IDE всплеском «meh», так что здесь - это то, чем я закончил.

5
задан xyz 18 June 2009 в 15:15
поделиться

7 ответов

  1. Как узнать, реализует ли он IDisposable всего за 1 или 1 и 2 выше?

Ответ на ваш первый вопрос: «вам не нужно знать». Если вы используете сторонний код, то в какой-то момент вы его милость - вам придется верить, что он избавляется от себя должным образом, когда вы вызываете для него Dispose. Если вы не уверены или думаете, что это ошибка, вы всегда можете попробовать использовать Reflector (), чтобы разобрать ее (если возможно) и проверить, что он делает.

  1. Отвечаю ли я за то, чтобы неуправляемые ресурсы могли или могут не держать внутренне освобождены? Должен Я добавляю финализатор (это будет правильный механизм?) в мой собственный класс это зовёт instanceOfMsSuppliedClass.Dispose ()?

Если вы используете .Net 2.0 или выше, то редко, если вообще когда-либо, нужно реализовать финализатор для ваших классов. Финализаторы добавляют накладные расходы вашему классу и обычно не предоставляют дополнительных функций, которые вам понадобились бы при простой реализации Dispose. Я настоятельно рекомендую посетить эту статью , чтобы получить хороший обзор правильной утилизации. В вашем случае вы можете вызвать instanceofMSSuppliedClass.Dispose () в своем собственном методе Dispose ().

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

10
ответ дан 18 December 2019 в 09:52
поделиться

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

using (var myObj = new Whatever())
{
   // ..
}

похоже на

{
  var myObj;
  try
  {
     myObj = new Whatever();
     // ..
  } 
  finally
  {
    if (myObj != null)
    {
      ((IDisposable)myObj).Dispose();
    }
  }
} // object scope ends here

EDIT : добавлено try / finally благодаря Talljoe - вау, это сложно поймите это правильно :)

EDIT2: Я не говорю, что вы должны использовать второй вариант. Я просто хотел показать, что «использование» - хороший синтаксический сахар для кучи кода, который может стать довольно беспорядочным и трудным для правильного выполнения.

0
ответ дан 18 December 2019 в 09:52
поделиться

Вы всегда должны вызывать Dispose для объектов, реализующих IDisposable (если только они специально не сообщают вам, что это полезное соглашение, например HtmlHelper.BeginForm в ASP.NET MVC). Вы можете использовать оператор using, чтобы упростить это. Если вы используете ссылку на IDisposable в своем классе в качестве поля-члена, вам следует реализовать IDisposable, используя Disposable Pattern , чтобы очистить эти элементы. Если вы запустите инструмент статического анализа, такой как FxCop, он скажет вам то же самое.

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

5
ответ дан 18 December 2019 в 09:52
поделиться

Вы не несете ответственности за содержимое объекта. Dispose () должен быть прозрачным и освобождать то, что ему нужно. После этого вы не несете за это ответственности.

Неуправляемые ресурсы - это ресурсы, которые вы создали бы в (управляемом) C ++, где вы распределяете память с помощью указателей и «новых» операторов, а не операторов «gcnew». Когда вы создаете класс на C ++, вы несете ответственность за удаление этой памяти, поскольку это внутренняя память или неуправляемая, и сборщик мусора не об этом. Вы также можете создать эту неуправляемую память с помощью выделения Marshal и, i ' Предполагается, что это небезопасный код.

При использовании Managed C ++ вам также не нужно вручную реализовывать класс IDisposable. Когда вы напишете свой деконструктор, он будет скомпилирован в функцию Dispose ().

1
ответ дан 18 December 2019 в 09:52
поделиться

Здесь не хватает финализатора. Моя привычка заключалась в том, что если я реализую IDisposable, у меня также есть финализатор для вызова Dispose () на случай, если мой клиент этого не сделает. Да, это добавляет накладные расходы, но если вызывается Dispose () IS, то вызов GC.SuppressFinalize (this) устраняет его.

-1
ответ дан 18 December 2019 в 09:52
поделиться

Если класс, о котором идет речь, предоставлен Microsoft (например, база данных и т. д.), то обработка Dispose (из IDisposable), скорее всего, уже будет выполнена, вам остается только ее вызвать. Например, стандартная практика использования базы данных будет выглядеть так:

//...
using (IDataReader dataRead = new DataReaderObject())
{
   //Call database
}

По сути, это то же самое, что писать:

IDataReader dataRead = null;
try
{
    dataRead = new DataReaderObject()
    //Call database
}
finally
{
    if(dataRead != null)
    {
        dataRead.Dispose();
    }
}

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

Что касается использования IDisposable самостоятельно, реализация зависит от вас. После того, как вы унаследуете его, вы должны убедиться, что метод содержит код, необходимый для удаления любых подключений к БД, которые вы могли создать вручную, освобождения ресурсов, которые могут остаться, или предотвращения уничтожения объекта, или просто очистки больших пулов ресурсов (например, изображений ). Это также включает в себя неуправляемые ресурсы, например, код, помеченный внутри «небезопасного» блока, по сути, является неуправляемым кодом, который может допускать прямые манипуляции с памятью, что определенно требует очистки.

После того, как вы унаследуете его, вы должны убедиться, что метод содержит код, необходимый для удаления любых подключений к БД, которые вы могли создать вручную, освобождения ресурсов, которые могут остаться, или предотвращения уничтожения объекта, или просто очистки больших пулов ресурсов (например, изображений ). Это также включает в себя неуправляемые ресурсы, например, код, помеченный внутри «небезопасного» блока, по сути, является неуправляемым кодом, который может допускать прямые манипуляции с памятью, что определенно требует очистки.

После того, как вы унаследуете его, вы должны убедиться, что метод содержит код, необходимый для удаления любых подключений к БД, которые вы могли создать вручную, освобождения ресурсов, которые могут остаться, или предотвращения уничтожения объекта, или просто очистки больших пулов ресурсов (например, изображений ). Это также включает в себя неуправляемые ресурсы, например, код, помеченный внутри «небезопасного» блока, по сути, является неуправляемым кодом, который может допускать прямые манипуляции с памятью, что определенно требует очистки.

1
ответ дан 18 December 2019 в 09:52
поделиться

Почему это должно иметь для вас значение?

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

Не требуется по причине 1 или по причине 2.

0
ответ дан 18 December 2019 в 09:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: