Каковы наиболее производные исключения? - PullRequest
2 голосов
/ 06 января 2011


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

catch(formatException)
//this is derived from Exception

catch(OutoFMemoryException) 
// this is derived from ArithmeticException whic is derived from Exception

Ответы [ 9 ]

2 голосов
/ 06 января 2011

CLR проходит через блоки захвата в указанном порядке.

Если он находит оператор catch с типом исключения, который соответствует текущему исключению, или исключением, которое наследуется от текущего исключения, то будет вызван этот блок.

2 голосов
/ 06 января 2011

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

Например, в коде ниже:

int x = 4 / (1 - 1);

Вы получите исключение типа DivideByZeroException, которое является ArithmeticException, которое является Исключением.

Так как бы вы использовали это?

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

Если вы знаете, что можете получить исключение DivideByZeroException, для этого вы устанавливаете блок catch и обрабатываете его так, как должны. И вы также должны добавить улов для более общего типа исключения:

try
{
    int x = 4 / (1 - 1);
    // More Stuff
}
catch(DivideByZeroException ex)
{
    // Here we know we got an exception on that division
}
catch(Exception ex)
{
   // Here we know something went wrong on that "more stuff"
}

Вы можете облегчить решение проблем таким способом.

1 голос
/ 06 января 2011

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

В этом случае первый блок catch уже перехватывает все исключения этого или супертипа ('System.Exception') ". Это и есть причина заказа для исключения.

try
{
 throw new formatException();
}


catch(Exception ex)
{
    <...>
}
catch(formatException ex)
{
    <...>
}

Редактировать -

Если вы посмотрите на иерархию наследования класса FormatException -

  System.Exception
    System.SystemException
      System.FormatException

и иерархия наследования класса OutOfMemoryException -

  System.Exception
    System.SystemException
      System.OutOfMemoryException

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

Например, если у вас есть два блока catch - FormatException и Exception, вам нужно будет позаботиться о порядке блоков catch, поскольку класс FormatException наследуется от класса Exception. Если блок перехвата Exception помещен перед блоком перехвата FormatException, то каждое исключение перехватывается блоком перехвата Exception (даже исключение формата). Если у вас есть блок перехвата FormatException до блока перехвата Exception, то исключение формата перехватывается конкретным блоком перехвата FormatException, но все другие исключения перехватываются блоком перехвата Exception.

Но если у вас есть два блока catch, таких как FormatException и OutOfMemoryException. Тогда вам не нужно беспокоиться о порядке, так как эти два класса не являются базовыми или производными друг от друга. Таким образом, они просто конкретные исключения.

Итак, вы можете иметь либо -

try
{
 throw new formatException();
}
catch(OutOfMemoryException ex)
{
    <...>
}
catch(FormatException ex)
{
    <...>
}

или

try
{
 throw new formatException();
}  
catch(FormatException ex)
{
    <...>
}
catch(OutOfMemoryException ex)
{
    <...>
}

Это не будет иметь значения, потому что, независимо от того, в каком порядке формируется исключение, он всегда перехватывается конкретным блоком перехвата FormatException. То же самое для OutOfMemoryException. Надеюсь, это ответит на ваш вопрос.

1 голос
/ 06 января 2011

Оператор try-catch состоит из блока try, за которым следует одно или несколько предложений catch, которые определяют обработчики для различных исключений.

Когда генерируется исключение, общеязыковая среда выполнения (CLR) ищет оператор catch, который обрабатывает это исключение.

Если выполняемый в настоящее время метод не содержит такогов блоке catch CLR просматривает метод, вызвавший текущий метод, и так далее в стеке вызовов.

Если блок перехвата не найден, CLR отображает необработанное сообщение об исключении для пользователя и останавливает выполнение программы.

Выше найден @ msdn

CLR останавливается на первом блоке перехвата, который может обработать исключение.Кто бы ни был первым в списке.

1 голос
/ 06 января 2011

Это также зависит от типа создаваемого исключения, которое будет определять, какой блок catch вызывается. Так как у вас есть определенная уловка для FormatException, то, если выдается FormatException, она будет отловлена ​​этим уловом, только если улов Exception не определен до него. Если вы не определили улов FormatException, то улов Exception будет обрабатывать FormatException, поскольку он происходит от Exception.

1 голос
/ 06 января 2011

Нет необходимости, даже если OverflowException происходит от ArithmeticException, их самый распространенный знаменатель - Exception.

Вы можете видеть это как некое подобие древовидной структуры, где FormatException и OverflowException находятся по разные стороны дерева. Если OverflowException унаследовано от FormatException, ситуация будет иной, но это не так.

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

0 голосов
/ 06 января 2011

@ Loj, вы можете концептуально рассматривать операторы catch как оператор switch (мы не можем написать оператор switch как этот, но тем не менее):

switch (caughtException) 
{ 
   case (caughtException is FormatException):...;
   case (caughtException is OverflowException):...; 
   case (caughtException is Exception):...; 
   etc.  

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

В вашем примере OutOfMemoryException «удален» из Exception больше, чем FormatException, но это не создает проблемы, поскольку проверка caughtException is FormatException возвращает false, и мы переходим к следующей возможности. *

0 голосов
/ 06 января 2011

Дело в том, что подкласс будет первым, затем базовый класс

0 голосов
/ 06 января 2011

Работает в иерархии, а OverflowExceptiona и FormatException находятся в разных ветвях и имеют общий общий класс исключений.

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