Одноразовые товары, блоки «Использование» и «Попробуй/поймай»

У меня сегодня ментальный блок, нужна помощь, чтобы проверить, не ошиблась ли моя логика.

Традиционно я бы делал файловый ввод/вывод примерно так:

FileStream fs = null; // So it's visible in the finally block
try
{
   fs = File.Open("Foo.txt", FileMode.Open);

   /// Do Stuff
}
catch(IOException)
{
   /// Handle Stuff
}
finally
{
   if (fs != null)
      fs.Close();
}

Однако это не очень элегантно.

В идеале я хотел бы использовать блок using для удаления файлового потока, когда я закончу, однако я не уверен в синергии между использованием и попыткой/поймать.

Вот как я хотел бы реализовать вышеизложенное:

try
{
   using(FileStream fs = File.Open("Foo.txt", FileMode.Open))
   {
      /// Do Stuff
   }
}
catch(Exception)
{
   /// Handle Stuff
}

Однако я обеспокоен тем, что преждевременный выход (через выброшенное исключение) из блока использования может не позволить блоку использования завершить выполнение и очистить свой объект. Я просто параноик, или это действительно сработает так, как я задумал?


person Aren    schedule 28.04.2010    source источник


Ответы (6)


Вы просто параноик, и это сработает так, как вы задумали :)

Оператор using эквивалентен блоку try/finally независимо от того, находится он внутри блока try/catch или нет.

Итак, ваш код похож на:

try
{
   FileStream fs = null;
   try
   {
       fs = File.Open("Foo.txt", FileMode.Open);
       // Do stuff
   }
   finally
   {
       if (fs != null)
       {
           fs.Dispose();
       }
   }
}
catch(Exception)
{
   /// Handle Stuff
}
person Jon Skeet    schedule 28.04.2010

Не волнуйтесь, он очистится, как и ожидалось, и будет чище, чем ваш оригинал.

На самом деле гораздо чаще используется оператор try/finally, также известный как using, в вашей бизнес-логике и try/catch в обработчике верхнего уровня на уровне пользовательского интерфейса или на границе физического уровня. Что-то типа:

try
{
    DoStuffWithFile("foo.txt");
}
catch(Exception ex)
{
   ...
}

а также

public void DoStuffWithFile(string fileName)
{
    using(FileStream fs = File.Open(fileName,...))
    {
        // Do Stuff
    }
}
person Joe    schedule 28.04.2010

Это будет работать - внутри оператор using компилируется так же, как блок try-finally.

person Ray    schedule 28.04.2010

    try
    {
        FileStream fs = null;
        try
        {
           fs = File.Open("Foo.txt", FileMode.Open);

        }
        finally
        {
           fs.Dispose();
        }
    }
    catch(Exception)
    {
       /// Handle Stuff
    }

второй кусок кода переводится в этот

person Andrey    schedule 28.04.2010

Блок using будет работать именно так, как вы задумали. Блок using на самом деле просто

try
{
   FileStream fs = null;
   try
   {
        fs = File.Open("Foo.txt", FileMode.Open))
        //Do Stuff
   }
   finally
   {
      if(fs != null)
          fs.Dispose();
   }
}
catch(Exception)
{
   /// Handle Stuff
}
person Scott Chamberlain    schedule 28.04.2010

Вам не нужен try..finally, если у вас есть using(). Они выполняют одну и ту же операцию.

Если вы не уверены, наведите Reflector на свою сборку и сравните сгенерированный код. .

person 3Dave    schedule 28.04.2010