Что удаляется при использовании ключевого слова used

Давайте рассмотрим пример:

using (var someObject = new SomeObject())
{
    var someOtherObject = new SomeOtherObject();
    someOtherObject.someMethod(); 
}

SomeOtherObject также реализует IDisposable. Будет ли SomeOtherObject также удален, когда SomeObject будет удален? Что произойдет с SomeOtherObject ? (удаление SomeOtherObject не реализовано в методе Dispose SomeObject)


person user137348    schedule 05.03.2010    source источник


Ответы (8)


Нет. Будут удалены только поля в предложении using. В вашем случае только someObject.

В основном этот код переводится в

var someObject = null;
try
{
  someObject = new SomeObject()

  var someOtherObject = new SomeOtherObject();
  someOtherObject.someMethod(); 
}
finally
{
  if (someObject != null )
  someObject.Dispose()
}
person munissor    schedule 05.03.2010
comment
Обратите внимание, что someObject = new SomeObject() размещается перед блоком try! - person Sergey Teplyakov; 05.03.2010

Нет, SomeOtherObject не будет удалено.

Ваш код реструктурируется компилятором следующим образом:

var someObject = new SomeObject();
try
{
    var someOtherObject = new SomeOtherObject();
    someOtherObject.someMethod(); 
}
finally
{
    if (someObject != null)
        someObject.Dispose();
}
person Henk Holterman    schedule 05.03.2010

Никакой someOtherObject не будет удален.

Ваш код будет транслироваться примерно так:

var someObject = new SomeObject();
try
{
   var someOtherObject = new SomeOtherObject();
   someOtherObject.someMethod(); 
}
finally
{
    ((IDisposable)someObject).Dispose();
}

Таким образом, не будет выполняться никаких дополнительных обращений к какому-либо вновь созданному объекту.

person Sergey Teplyakov    schedule 05.03.2010

цитата из MSDN напрямую:

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

Таким образом, будет удален только объект, объявленный и созданный в операторе использования. Для такого рода проблем я бы посоветовал вам сделать тест, прежде чем публиковать вопрос.

person Jay Zhu    schedule 05.03.2010

someOtherObject будет нормально собираться сборщиком мусора. Если вы не предоставили соответствующий финализатор (деструктор), который вызывает Dispose(), он никогда не будет вызван. Только someObject.Dispose() будет вызываться, когда поток выполнения покинет блок using.

person Gorpik    schedule 05.03.2010

Вы должны написать это так:

using (var someObject = new SomeObject()) {
    using (var someOtherObject = new SomeOtherObject()) {
        someOtherObject.someMethod(); 
    }
}

Это может выйти из-под контроля, если ваш метод создает много одноразовых объектов, обычных в коде рисования. Рефакторинг во вспомогательный метод или переход к явному блоку finally.

person Hans Passant    schedule 05.03.2010
comment
Кстати, нет необходимости делать еще одну оговорку { }. Использование может стек. Удалите первый { и последний}, и все будет хорошо :) - person RvdK; 05.03.2010
comment
@PoweRoy: конечно, это не настоящий код, OP, несомненно, где-то действительно использует переменную someObject. - person Hans Passant; 05.03.2010

Метод Dispose объекта, на который ссылается someObject, будет вызываться, когда управление покинет блок using. Вы можете SuppressFinalize в методе Dispose, и в этом случае система не будет вызывать finalizer этого объекта (в противном случае она будет).
Однако объект, на который ссылается someOtherObject, будет собран сборщиком мусора в соответствующее время, потому что когда элемент управления покидает блок , на него не будет ссылаться какой-либо объект, и он будет помечен для сбора.

person ata    schedule 05.03.2010

Не уверен, что это то, откуда вы пришли; someOtherObject не будет доступен за пределами блока using; из-за правил области действия.

using (Stream stream = File.OpenRead(@"c:\test.txt"))
{
   var v1 = "Hello"; //object declared here, wont be accessible outside the block
   stream.Write(ASCIIEncoding.ASCII.GetBytes("This is a test"), 0, 1024);
} //end of scope of stream object; as well as end of scope of v1 object.

v1 = "World!"; //Error, the object is out of scope!

Ошибка компилятора: «Имя v1 не существует в текущем контексте».

Даже следующее вызовет ошибку.

    {
        int x=10;
    }

    x = 20; //Compiler error: "The name x does not exist in the current context."

См. это и это для получения дополнительной помощи.

person KMån    schedule 05.03.2010