Чи використовується твердження використання лише перша змінна, яку вона створює?

Скажімо, у мене є одноразовий об'єкт MyDisposable , який в якості параметра конструктора використовує інший одноразовий об'єкт.

using(MyDisposable myDisposable= new MyDisposable(new AnotherDisposable()))
{
     //whatever
}

Припускаючи, що myDisposable не використовуйте метод AnotherDisposable в його розпорядженні.

Чи правильно він розпоряджається myDisposable ? чи це також розпоряджається AnotherDisposable ?

6
Так, він не має розпорядження AnotherDisposable , потрібно керувати вручну
додано Автор Cuong Le, джерело
AnotherDisposable слід розмістити на MyDisposable реалізацію, оскільки вона використовується там.
додано Автор AgentFire, джерело

8 Відповіді

using is an equivalent of

MyDisposable myDisposable = new MyDisposable(new AnotherDisposable());
try
{
    //whatever
}
finally
{
    if (myDisposable != null)
        myDisposable.Dispose();
}

Таким чином, якщо myDisposable не викликає Dispose на AnotherDisposable , , використовуючи також не буде викликати це.

9
додано
Красива чітка відповідь.
додано Автор Sander, джерело
Відмінно це насправді відповісти на моє запитання
додано Автор Fabio Marcolini, джерело

Чому б не гніздити їх?

using(var outer = new AnotherDisposable())
{
   using(var inner = new MyDisposable(outer))
   {
      //whatever
   }

}

Тепер, принаймні, ви можете бути впевнені, що вони будуть звільнені правильно.

5
додано
+1, найкращий спосіб обробки очищення. Як примітка, другий набір дужок навіть не потрібний. Це зводиться до вашого уподобання форматування, але ви можете створити заявки з використанням безпосередньо один на одного та використовувати ті самі дужки, щоб позначити область застосування.
додано Автор Amicable, джерело
проблема полягає в тому, що, використовуючи подвійне використання, FxCop показує CA2202: об'єкт не повинен бути розміщений кілька разів, але це тому, що в реальному випадку я використовую, я знаю, innerDisposable розміщується outerDisposable так що я думаю, якщо це може бути зроблено
додано Автор Fabio Marcolini, джерело

Він не "розпоряджається" нічим. Він називає метод Dispose об'єкта, що використовується в ньому. Це ваша робота, щоб очистити що-небудь ще .. можливо, покликавши розпоряджатися іншим об'єктом.

1
додано

Заява про використання C# забезпечує синтаксичний ярлик для виклику Dispose на об'єктах які реалізують IDisposable, використовуючи спроб/остаточний блок. Наприклад:

using (FileStream fs = new FileStream ("myFile.txt", FileMode.Open))
{
// ... Write to the file ...
}

Компілятор перетворює це на: FileStream fs = новий FileStream ("myFile.txt", FileMode.Open);

try
{
// ... Write to the file ...
}
finally
{
if (fs != null) ((IDisposable)fs).Dispose();
}

Нарешті, блок гарантує, що метод Dispose викликається навіть у випадку винятку кидається 1, або код виходить з блоку рано.

Таким чином, для використання одного блоку буде забезпечено лише те, що буде розміщений єдиний одноразовий об'єкт. З іншого боку, ви можете використовувати вкладене використання твердження. люблю

using (myDisposable d = new myDisposable())
{
  using(Disposable2 d2 = new Disposable2())
  {
// do something and dispose...
  }
}

і це буде перетворено як

try
{
 //work around for myDisposable  

    try
     {
     //work around for Disposable2 
     }
    finally
    {
    if (d2 != null) 
         ((IDisposable)d2 ).Dispose();
    }    
}
finally
{
     if (d!= null)
          ((IDisposable)d).Dispose();
}
0
додано

Заява про використання C# забезпечує синтаксичний ярлик для виклику Dispose на об'єктах які реалізують IDisposable, використовуючи спроб/остаточний блок. Наприклад:

using (FileStream fs = new FileStream ("myFile.txt", FileMode.Open))
{
// ... Write to the file ...
}

Компілятор перетворює це на: FileStream fs = новий FileStream ("myFile.txt", FileMode.Open);

try
{
// ... Write to the file ...
}
finally
{
if (fs != null) ((IDisposable)fs).Dispose();
}

Нарешті, блок гарантує, що метод Dispose викликається навіть у випадку винятку кидається 1, або код виходить з блоку рано.

Таким чином, для використання одного блоку буде забезпечено лише те, що буде розміщений єдиний одноразовий об'єкт. З іншого боку, ви можете використовувати вкладене використання твердження. люблю

using (myDisposable d = new myDisposable())
{
  using(Disposable2 d2 = new Disposable2())
  {
// do something and dispose...
  }
}

і це буде перетворено як

try
{
 //work around for myDisposable  

    try
     {
     //work around for Disposable2 
     }
    finally
    {
    if (d2 != null) 
         ((IDisposable)d2 ).Dispose();
    }    
}
finally
{
     if (d!= null)
          ((IDisposable)d).Dispose();
}
0
додано

У цьому випадку він не буде розпоряджатися AnotherDisposable . Є два рішення для цього.

По-перше, що ви, як правило, зробите, це наступне:

using (AnotherDisposable anotherDisposable = new AnotherDisposable())
using (MyDisposable myDisposable= new MyDisposable(anotherDisposable))
{
}

Проте існує інший спосіб піти. Звичайно, коли клас приймає одноразовий, він сам потурбується про розпорядження об'єктом, який він взяв. Наприклад, StreamReader , який обгортає Stream , буде використано Stream , він обгортає. Це означає, що конструкція, яку ви виберете, буде працювати. Ви можете застосувати цю саму функцію в MyDisposable , а тоді підхід, який ви взяв, буде в порядку.

0
додано
Шаблон використовуючи шаблон MyDisposable myDisposable = new MyDisposable (new AnotherDisposable ()) {...} буде безпечним, якщо конструктор для MyDisposable обіцяє не тільки те, що MyDisposable.Dispose буде розпоряджатися об'єктом, переданим у конструктор, але також, якщо в ході самого конструктора виникне якесь виключення, то елемент, що був переданий, буде негайно вилучено - це візерунок, який набагато важче, ніж це має бути отримати право.
додано Автор supercat, джерело

Ви тільки ініціалізували одну одноразову змінну в операторі , що використовує . Вкладений об'єкт AnotherDisposable створюється за допомогою звичайної ініціалізації, а не за допомогою з використанням . Таким чином, лише змінна myDisposable , яку ви створили з використанням , що використовує , буде автоматично розміщена на ній.

0
додано

Ви тільки ініціалізували одну одноразову змінну в операторі , що використовує . Вкладений об'єкт AnotherDisposable створюється за допомогою звичайної ініціалізації, а не за допомогою з використанням . Таким чином, лише змінна myDisposable , яку ви створили з використанням , що використовує , буде автоматично розміщена на ній.

0
додано
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug