Какова связь между ключевым словом using и интерфейсом IDisposable? - PullRequest
5 голосов
/ 23 августа 2010

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

Ответы [ 7 ]

13 голосов
/ 23 августа 2010

Вы не можете иметь одно без другого.

Когда вы пишете:

using(MyClass myObj = new MyClass())
{
    myObj.SomeMthod(...);
}

Компилятор сгенерирует что-то вроде этого:

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

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

12 голосов
/ 23 августа 2010

Если вы используете оператор using , то вложенный тип должен уже реализовывать IDisposable, иначе компилятор выдаст ошибку.Поэтому считайте, что реализация IDisposable является обязательным условием использования.

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

// To implement it in C#:
class MyClass : IDisposable {

    // other members in you class 

    public void Dispose() {
        // in its simplest form, but see MSDN documentation linked above
    }
}

Это позволяет вам:

using (MyClass mc = new MyClass()) {

    // do some stuff with the instance...
    mc.DoThis();  //all fake method calls for example
    mc.DoThat();

}  // Here the .Dispose method will be automatically called.

Фактически это то же самое, что писать:

MyClass mc = new MyClass();
try { 
    // do some stuff with the instance...
    mc.DoThis();  //all fake method calls for example
    mc.DoThat();
}
finally { // always runs
    mc.Dispose();  // Manual call. 
}
5 голосов
/ 23 августа 2010

Вы путаете вещи. Вы можете использовать ключевое слово «using» только для того, что реализует IDisposable.

Редактировать: если вы используете ключевое слово using, вам не нужно, чтобы explicity вызывало Dispose, оно будет вызываться автоматически в конце блока using. Другие уже опубликовали примеры того, как оператор using преобразуется в оператор try - finally с вызовом Dispose в блоке finally.

4 голосов
/ 23 августа 2010

Да, ключевое слово using является синтаксическим сахаром для этого типа шаблона ... (из msdn)

  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }

Редактировать: полезный пример.

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

  public class Busy : IDisposable
  {

    private Cursor _oldCursor;

    private Busy()
    {
      _oldCursor = Cursor.Current;
    }

    public static Busy WaitCursor
    {
      get
      {
        Cursor.Current = Cursors.WaitCursor;
        return new Busy();
      }
    }

    #region IDisposable Members

    public void Dispose()
    {
      Cursor.Current = _oldCursor;
    }

    #endregion
  }

Называется как ...

using(Busy.WaitCursor)
{
  // some operation that needs a wait cursor.
}
2 голосов
/ 23 августа 2010

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

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

КакПравило, когда вы используете объект IDisposable, вы должны объявить и создать его экземпляр в операторе using.Оператор using корректно вызывает метод Dispose для объекта, а также вынуждает сам объект выходить из области действия при вызове Dispose.Внутри блока using объект доступен только для чтения и не может быть изменен или переназначен.

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

1 голос
/ 23 августа 2010

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

error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable'
1 голос
/ 23 августа 2010

Ключевое слово using уже реализовано, поэтому, если вы используете ключевое слово using, вам не нужно вызывать IDisposable

...