Какова связь между ключевым словом using и интерфейсом IDisposable?

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

7 ответов

Решение

Если вы используете 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. 
}

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

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

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 был реализован.

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

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

Да, ключевое слово 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.
}

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

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

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

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

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

error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable'

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

Другие вопросы по тегам