C #: IDisposable классы нуждаются в предложении «using»? - PullRequest
2 голосов
/ 02 марта 2011

Если я использую класс IDisposable, я должен всегда использовать предложение using, например:

using (MyClass myclass = new MyClass())
{
...
}

Ответы [ 7 ]

4 голосов
/ 02 марта 2011

Оператор using гарантирует, что Dispose вызывается для освобождения ресурсов, даже если возникает исключение или объект выходит из области видимости.

Это проще, чем использовать следующий блок кода,

try
{
   ...
}
catch()
{
   // Handle exception
}
finally
{
    // Free resources by calling Dispose()
}

Примечание
Блок catch не требуется, если не требуется обрабатывать exception. В этом случае достаточно блока try ... finally (как указано в других ответах).


Альтернативный способ
Вы можете создать несколько экземпляров одноразового объекта в одном и том же операторе using, например

using(MyClass myclass1 = new MyClass(), 
      MyClass myclass2 = new MyClass())
{
    ...
}


* +1025 * Пример
С Понимание оператора using в C #

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

переводится в ( CLR )

MyResource myRes= new MyResource();
try
{
    myRes.DoSomething();
}
finally
{
    // Check for a null resource.
    if (myRes!= null)
    {
        // Call the object's Dispose method.
        ((IDisposable)myRes).Dispose();
    }
}

Вы можете взглянуть на сгенерированный MSIL по ссылке, указанной в начале примера.


Дополнительная информация

2 голосов
/ 02 марта 2011

Это делает его намного более читабельным кодом. Таким образом, как правило, вы должны объявить и создать экземпляр объекта в блоке using. Это гарантирует, что метод Dispose вызывается, даже если происходит исключение. Во время компиляции то же выражение будет выглядеть примерно так: this :

{
  MyClass myclass = new MyClass ();
  try {
    //Do something with myclass
  }
  finally {
    if (myclass != null)
      ((IDisposable)myclass).Dispose();
  }
}
0 голосов
/ 03 марта 2011

Существует три сценария создания объекта IDisposable:

  1. Объект понадобится некоторое время, но не понадобится после выхода из текущего блока кода.
  2. Объект будет передан вызывающей стороне текущей подпрограммы, которая затем будет отвечать за него.
  3. Класс, отвечающий за объект IDisposable, сохраняет его в поле, чтобы он был доступен для использования в будущих вызовах методов / свойств.

В сценарии № 1 используйте блок «using» для создания объекта;его очистка будет выполняться автоматически.

В сценарии № 2 используйте блок try-finally с переменной «ok», для которой изначально установлено «False», но в конце «True»«попробуй» или перед любым возвратом;в конечном итоге, если «oK» равно false, вызовите Dispose, чтобы убедиться, что частично сконструированный объект очищен.

В сценарии № 3 сохраните объект в поле, как только он будет создан, и определитеМетод IDisposable.Dispose, который копирует значение в поле в переменную, обнуляет поле и, если переменная отлична от NULL, утилизирует его (если есть вероятность того, что несколько потоков вызывают Dispose одновременно, используйте Interlocked.Exchange для фиксациии очистить поле).Конструкторы также должны быть защищены, как если бы они работали в сценарии № 2.

0 голосов
/ 02 марта 2011

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

0 голосов
/ 02 марта 2011

Проще говоря, если он реализует IDisposable, и вы хотите, чтобы этот метод вызывался (также для исключений в блоке finally, когда вы это делаете. Используйте using.

GC НЕ будет вызывать Dispose () дляВы! Некоторые классы реализуют финализатор ~ ClassName (), но старайтесь избегать этого, потому что он имеет много побочных эффектов и неочевиден.

Вы можете прочитать оператор using как:

TestClass test = new TestClass();
try
{
      test.DoSomething();
}
finally
{
      test.Dispose();
}
0 голосов
/ 02 марта 2011

Если класс реализует IDisposable, вы всегда должны вызывать Dispose, когда закончите с объектом. C # обеспечивает использование оператора в качестве синтаксического сахара, чтобы сделать это проще. Таким образом, нет необходимости использовать using для вызова Dispose. Тем не менее, это де-факто стандартный способ вызова Dispose. то есть, если ваш код не использует using и вместо этого вызывает Dispose в блоках finally, он будет выглядеть немного странно для опытных программистов.

Расширение используемого вами блока (при условии, что MyClass является ссылочным типом):

{
    MyClass myclass = new MyClass();
    try {
        //...
    }
    finally {
        if (myclass != null) ((IDisposable)myclass).Dispose();
    }
}

Версия using легче кодируется и легче читается.

0 голосов
/ 02 марта 2011

предложение using является синтаксическим сахаром в следующем блоке кода:

MyClass myclass = null;
try
{
     myclass = new MyClass();
     //do work
}
finally
{
     if(myclass != null)
          myclass.Dispose();
}

Если класс реализует IDisposable, вы должны убедиться, что Dispose вызывается, когда вы его используете.Предложение using - это простой способ сделать это.Таким образом, вам не нужно использовать «использование», чтобы сделать это, но вы должны убедиться, что он вызывается.

...