Как мне безопасно инициализировать, а затем использовать переменную в разных блоках try? - PullRequest
0 голосов
/ 20 июля 2011

Итак, мне нужно создать файл с использованием класса StreamWriter, записать в него, а затем закрыть его, и я хочу поместить все потенциально неисполняемые операции в блоки try; и поскольку операции создания и записи файла будут выполняться в разных блоках try, я не могу инициализировать переменную StreamWriter (создать файл) в одном блоке try, а затем использовать его в другом. Я думаю, я мог бы объявить переменную StreamWriter вне блоков try и установить ее в null, а затем инициализировать ее в блоке try, но MSDN говорит: «Внутри блока try инициализируйте только переменные, которые в нем объявлены; в противном случае может возникнуть исключение. до завершения выполнения блока ". Какова наилучшая практика для безопасного объявления, инициализации, использования переменной потока файла (или любой другой переменной), а затем ее удаления? Может, мне стоит использовать что-то вместо StreamWriter? Кроме того, почему бы вам не инициализировать переменную в блоке try, если вы не объявили ее там? Спасибо.

Ответы [ 8 ]

2 голосов
/ 20 июля 2011

Вы можете объявить это вне блоков try, просто убедитесь, что вы правильно утилизировали.

StreamWriter sw = null;

try
{
    sw = new StreamWriter(File.Open("test.txt", FileMode.OpenOrCreate));
    sw.Write("Some text.");
}
catch
{
    // Whatever you want to catch
}
finally
{
    if(sw != null)
        sw.Dispose();

    sw = null;  
}


try
{
    sw = new StreamWriter(File.Open("otherfile.txt", FileMode.OpenOrCreate));
}
catch
{
    // Whatever you want to catch
}
finally
{
    if(sw != null)
        sw.Dispose();

    sw = null;  
}

Хотя я бы не советовал использовать одну и ту же переменную в нескольких пробных блоках, что вы получаете от этого?

Почему бы не что-то вроде этого:

try
{
    using(var sw = new StreamWriter(File.Open("text.txt", FileMode.OpenOrCreate)))
    {
        sw.Write("some text");
    }
}
catch
{
    // handle exception
}


try
{
    using(var sw = new StreamWriter(File.Open("otherfile.txt", FileMode.OpenOrCreate)))
    {
        sw.Write("some other text");
    }
}
catch
{
    // handle exception
}
2 голосов
/ 20 июля 2011

Определяется ли StreamWriter на уровне класса, не метод?Я бы предложил использовать один блок try, если это возможно.

Если вам нужно обработать различные исключения, используйте несколько блоков catch для одного try, как предложено scottm

1 голос
/ 20 июля 2011

Я бы предложил использовать ключевое слово using, например:

  try {
  using(StreamWriter sw = new (...)) {
     //use stream here
  }
  }
  catch(Exception ex) {}

Использование гарантирует, что по замыслу StreamWriter будет закрыто и утилизировано при выходе из этого блока, даже если произойдет исключение, потому что using фактически вводит предложение try/finally в IL. Если это невозможно, я бы серьезно подумал о пересмотре архитектуры вызовов, если это возможно.

Общее правило для потоков ввода-вывода: открытие / использование / закрытие в кратчайшие сроки.

Привет.

1 голос
/ 20 июля 2011

Объявите ваш StreamWriter вне блока try ... catch, но не инициализируйте его. Выполните инициализацию внутри блока. В статье MSDN, на которую вы ссылаетесь, похоже, не очень хорошая идея, но я не понимаю, почему.

Объявление не выполнится, но инициализация может произойти.

В качестве альтернативы, вы можете вложить блоки try ... catch, чтобы вы могли объявить / инициализировать его во внешнем блоке и иметь дополнительные блоки try ... catch внутри него.

1 голос
/ 20 июля 2011

Время жизни StreamWriter должно управляться блоком using.

Ваш инстинкт перемещения объявления переменных за пределы двух блоков try является правильным, если вы хотите получить к нему доступ из обоих. Руководство MSFT просто пытается убедить вас, что в этом случае, если у вас есть возможные исключения, возникающие после объявления, но до блоков try они не будут перехвачены, но инициализация переменной в ноль не вызовет исключения, и если вы не сделаете ' не делай ничего, кроме того, что ты в порядке. (Если вы действительно беспокоитесь об этом, вы можете просто создать try / catch, который инкапсулирует объявление переменной, а также другие блоки try) Лично я не большой поклонник try / catch, но это проповедь для другого дня ...

1 голос
/ 20 июля 2011

Установка переменной в ноль при объявлении - это то же самое, что и инициализация. Он просто не содержит действительной ссылки на какой-либо реальный объект, но вы можете проверить это. Вы не можете проверить неинициализированные переменные: вы получите ошибки компиляции, если у вас есть возможный путь, который приводит к использованию неинициализированной переменной.

1 голос
/ 20 июля 2011

Я думаю, что MSDN означает, что вполне возможно, что при объявлении переменной типа T может быть вызван статический конструктор T, что вызовет исключение вне блока try.

В вашем примере я не вижу проблем с объявлением переменной вне блока try. Просто сделайте это, как предложено Скоттом.

1 голос
/ 20 июля 2011

Если вы хотите получить доступ к переменной в двух разных блоках try, вам нужно объявить ее вне обоих блоков (каким-то образом).Это простое управление областью действия.

Почему бы и нет?Я предполагаю, что причина в том, что вы можете вызвать исключение и не знать, инициализирована ли переменная.Таким образом, состояние в конце блока T / C / F является неопределенным.Если вы можете быть уверены, что состояние определено, то все в порядке, ИМО.

...