C # Exception Catching с использованием блоков try..catch - PullRequest
3 голосов
/ 15 июля 2011

Я новичок в C # и хотел лучше понять, как перехватывать исключения.Эти вопросы могут быть глупыми новичками.Они важны для меня, и я заранее извиняюсь.

Например, в классе Path System.IO, GetFullPath, может быть выброшено пять исключений: ArgumentException, SecurityException, ArgumentNullException, NotSupportedException и PathTooLongException.Я понимаю, что блоки перехвата должны быть организованы таким образом, чтобы сначала выявлялось самое конкретное исключение, а последним - самое общее исключение.

Вопрос 1. Когда MSDN предоставляет информацию о возможных исключениях, создаваемых классом, какузнать, какое исключение является наиболее конкретным, а какое наименее конкретным?Другими словами, как мне определить порядок исключений от наиболее специфического к наименее конкретному из того, что дает мне MSDN?

Вопрос 2: Нужно ли мне специально перехватывать все исключения явно или я буду использовать только наибольшее исключение родаперехватить все остальные исключения?Например, все еще используя класс Path, мне нужно сделать ...

try { ... }
catch(System.ArgumentNullException ane) { ... }
catch(System.NotSupportedException nse) { ... }
catch(System.IO.PathTooLongException ple) { ... }
catch(System.IO.SecurityException se) { ... }
catch(System.ArgumentException ae) { ... }

или просто ...

catch(System.ArgumentException ae) { ... }

перехватить все исключения?

Вопрос 3: является ли правильной синтаксическая структура для выполнения следующего в методе bool ...

try
{
  ... ;
  return true;
}
catch(System.ArgumentException ae)
{
  ... ;
  return false;
}

Ответы [ 5 ]

6 голосов
/ 15 июля 2011

Вопрос 1 :

В документации MSDN для каждого исключения вы можете видеть его цепочку наследования. Это говорит о том, какие из них более специфичны (чем ниже по цепочке, тем они конкретнее).

Вы также можете увидеть эту информацию в браузере объектов Visual Studio.

Вопрос 2 :

Хорошая практика - ловить исключения, с которыми можно что-то делать. Если вы не можете разумно что-либо сделать с исключением, пусть это всплывет.

В общем, лучше сначала отловить более конкретные исключения.

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

catch(System.ArgumentException ae) { ... }

Не поймает System.IO.SecurityException, поскольку System.IO.SecurityException не наследуется от System.ArgumentException.

Вопрос 3 :

Да, это правильный синтаксис.

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

3 голосов
/ 15 июля 2011

Несколько рекомендаций:

  1. Вы можете определить «специфику» исключений, посмотрев наследование наследования Исключений в MSDN. Если они являются производными от общего базового класса, исключение из базового класса является менее конкретным. Типичным примером является IOException, который является базовым классом для нескольких более конкретных исключений, связанных с вводом / выводом.

  2. Как правило, вы никогда не должны перехватывать исключения использования, такие как ArgumentException, ArgumentNullException, NotSupportedException и т. Д. Если они выбрасываются, они указывают на ошибки в вашем коде, которые должны быть исправлены. Они должны быть перехвачены только вашим «последним уловом» для регистрации и, возможно, форматирования ошибки для более удобного отображения перед закрытием приложения.


В ответ на комментарий:

Поймать исключение использования после факта для проверки ввода - плохая привычка, особенно если это делается путем перехвата Exception (так как это может маскировать другие неожиданные типы исключений.) Гораздо лучше проверить заранее. К сожалению, этот конкретный метод (Path.GetFullPath) не был разработан должным образом с учетом этих рекомендаций, поэтому вам необходимо обработать ArgumentException, NotSupportedException и PathTooLongException для проверки ввода пользователя. Вы можете сделать это в одном предложении catch, например:

try
{
     //Call Path.GetFullPath somewhere in here
}
catch (Exception ex)
{
     if (ex is ArgumentException || ex is NotSupportedException || ex is PathTooLongException)
     {
          //Your handling here
     }
     else
     {
          throw;
     }
}

Вы хотите, чтобы код внутри блока try был как можно короче, поскольку вы не хотите непреднамеренно подавлять другие исключения использования, кроме тех, которые могут быть сгенерированы Path.GetFullPath. Возможно, вы захотите обработать каждое исключение отдельно, так как вы можете использовать различия между ними, чтобы дать пользователю полезную информацию о том, что они сделали неправильно.

2 голосов
/ 15 июля 2011
  1. Когда вы указываете имя исключения как catch (System.ArgumentNullExcpetion), оно будет перехватывать только эти типы.Вы можете проверить описание наследования на странице документа исключения в msdn, чтобы проверить, являются ли более обобщенные исключения, и вам нужно беспокоиться только о них.

  2. Вы можете поймать самое общее исключение, но иногдаконкретные могут быть более полезными, когда вы кодируете и отлаживаете свою программу, и это может помочь вам узнать, какой тип исключения был выдан.

  3. Да, этот синтаксис можно использовать.

Inheritance chain for argument null exception

0 голосов
/ 15 июля 2011

1) В основном вы можете сказать, используя имена.(ArgumentNullException наследуется от ArgumentException, например).Когда вы не можете сказать по имени, вы можете просмотреть документацию или свой браузер объектов, и он должен дать вам дерево наследования.

2) Какие именно из них вы поймаете, будет зависеть от ваших потребностей.Многие скажут вам, что даже получение ArgumentException или ArgumentNullException означает, что вы, как разработчик, не смогли подтвердить вещи выше в своем вызове.

3) Если у вас было исключение, вы обычно нене хотите ничего возвращать - само исключение означает, что ваш метод не был завершен должным образом, что означает, что вы все равно не можете иметь хорошие данные для возвращаемого значения.Однако есть исключения из этого, поэтому YMMV.

0 голосов
/ 15 июля 2011

1) Специфика любого исключения основана на его иерархии наследования от более общих исключений базового класса.

2) Вы можете использовать общий улов, как показано ниже:

try
{
    ...
}
catch (System.Exception ex)
{
    ...
}

3) Да, это нормально, хотя вы, возможно, захотите уловить все, как показано в моем (2) ответе после более конкретного ArgumentException, который у вас уже есть.

...