Позволить исключению всплыть - PullRequest
4 голосов
/ 06 июля 2011

Как правильно разрешить всплыть исключению?
Если я использую Try-Catch при вызове метода, просто выдает исключение внутри метода, как если бы я вообще не пытался его перехватить?
Для иллюстрации: эти подходы работают одинаково?

Пример 1:

try
{
   MyFileHandlingMethod();             
}
catch (IOException ex)
{
   string recfilepath = "...
   string rectoadd = "RecDateTime=" + DateTime.Now.ToString()+ ...+ex.Message.ToString();
   File.AppendAllText(recfilepath, rectoadd);
}
catch (exception)
{
   throw;
}
...
MyFileHandlingMethod()
{
   ...
   TextReader tr2 = new StreamReader(nfilepath);
   resultN = tr2.ReadLine();
   tr2.Close();  
   ...
}

Пример 2:

try
{
   MyFileHandlingMethod();             
}
catch (IOException ex)
{
   string recfilepath = "...
   string rectoadd = "RecDateTime=" + DateTime.Now.ToString()+ ...+ex.Message.ToString();
   File.AppendAllText(recfilepath, rectoadd);
}
catch (exception)
{
   throw;
}
...
MyFileHandlingMethod()
{
   ...
     try
     {
        TextReader tr2 = new StreamReader(nfilepath);
        resultN = tr2.ReadLine();
        tr2.Close();              
     }
     catch (Exception)
     {
        throw;     
     }       
   ...
}

Ответы [ 4 ]

12 голосов
/ 06 июля 2011

Да, эти два подхода имеют почти одинаковый эффект;повторное бросание разматывает стек исключения - это означает, что стек укладывается «ниже» метода, в котором throw; будет отброшен.Они по-прежнему будут находиться в трассировке стека , но вы не сможете получить доступ к их локальным переменным в отладчике, если не разбьете на выброшенные исключения.

Блок захвата / выброса, подобныйнижеприведенный пример, в котором вы ничего не делаете с исключением (например, ведение журнала), бесполезен:

 catch (Exception)
 {
    throw;     
 } 

Удалите его, чтобы очистить оба образца.В общем, по возможности избегайте ввода блока catch


И у вашего метода есть еще одна проблема, связанная с исключением, он не освобождает ресурсы должным образом.tr2.Close(); принадлежит предложению finally, но гораздо проще позволить компилятору справиться с этим с помощью блока using() {}:

void MyFileHandlingMethod()
{
   ...
   using (TextReader tr2 = new StreamReader(nfilepath))
   {
     resultN = tr2.ReadLine();         
   } //tr2.Dispose() inserted automatically here        
   ...
}
2 голосов
/ 06 июля 2011

Да, результат тот же.

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

using (TextReader tr2 = new StreamReader(nfilepath)) {
  resultN = tr2.ReadLine();
}

Обратите внимание, что в этом коде нет Close.Блок using будет располагать StreamReader, который закроет поток.

Блок using скомпилирован в try ... finally, который он использует, чтобы убедиться, что StreamReader всегда расположен, но исключение будет вызывать вызывающий метод.

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

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

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

Я предлагаю вам использовать ваш первый пример со следующими изменениями:

try 
{
  MyFileHandlingMethod();              
} 
catch (IOException ex) 
{    
  string recfilepath = "...";
  string rectoadd = "RecDateTime=" + DateTime.Now.ToString()+ ex.Message.ToString();
  File.AppendAllText(recfilepath, rectoadd);
  throw;    // rethrow the same exception.
}
// no need for second catch}

Вы, вероятно, захотите сбросить исключение, как только вы зарегистрируете его, потому что вы не выполняете никакого фактического восстановления после ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...