С# Обработка исключений

Возможный дубликат:
Захват нескольких Исключений сразу?

Есть ли какой-либо способ в С#, чтобы легко достичь следующего pseduo-кода:

try
{
...
}
catch ( ExceptionTypeA, ExceptionTypeB, ExceptionTypeC as ex)
{
... same code for all threw
}

или

try
{
...
}
catch ( ExceptionTypeA ex )
catch ( ExceptionTypeB ex )
catch ( ExceptionTypeC ex )
{
... same code for all exceptions of A, B or C
}

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

Ответ 1

Проблема с указанным синтаксисом (с ex) заключается в следующем: какие свойства/члены должны ex иметь? Различные типы исключений не обязательно совместимы, если не существует наследования (в этом случае улавливайте наименее производные, о которых вы заботитесь).

Единственная текущая опция - просто использовать Exception ex (или подобное) и проверить (is/as) внутри обработчика.

Или; реорганизовать общий код в метод, который может использоваться всеми тремя?

Ответ 2

Короче говоря, нет. Я могу придумать два три альтернативы:

Поймать каждое исключение и вызвать общий метод:

try
{
   // throw
}
catch ( ExceptionTypeA ex )
{
     HandleException();
}
catch ( ExceptionTypeB ex )
{
     HandleException();
}
catch ( ExceptionTypeC ex )
{
     HandleException();
}

void HandleException()
{
}

Или поймайте все и используйте оператор if для типа:

try
{
   // throw
}
catch (Exception ex)
{
   if (ex is ArgumentException || ex is NullReferenceException || ex is FooException)
   {
      // Handle
   }
   else
   {
      throw
   }
}

EDIT: ИЛИ, вы можете сделать что-то вроде этого:

List<Type> exceptionsToHandle = new List<Type>{ typeof(ArgumentException), typeof(NullReferenceException), typeof(FooException) };

try
{
   // throw
}
catch (Exception ex)
{
   if (exceptionsToHandle.Contains(ex.GetType()))
   {
      // Handle
   }
   else
   {
      throw
   }
}

Ответ 3

Оберните повторяющийся код в методе.

try
{
...
}
catch ( ExceptionTypeA ex )
{
     DoSomething();
}
catch ( ExceptionTypeB ex )
{
     DoSomething();
}
catch ( ExceptionTypeC ex )
{
     DoSomething();
}
catch ( Exception ex )
{
     DoTheDefaultSomething();
}

Ответ 4

Вы можете получить общее исключение, а затем изучить тип, например:

catch (Exception ex)            
   {                
      if (ex is ExceptionTypeA ||
          ex is ExceptionTypeB )
           {
               /* your code here */
           }
       else
           {
               throw;
           }
    }

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

if (ex is ExceptionTypeA || ex is ExceptionTypeB )

это станет чем-то вроде:

if (IsRecoverableByDoingWhatever(ex))

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

Ответ 5

Если вам нужно использовать некоторые переменные из области try, используйте вложенную функцию. То есть, лямбда или анонимный делегат:

int x = ...;
Action<Exception> handler = delegate(Exception ex)
{
    // Same code for all exceptions of A, B or C.
    // You can use variable x here too.
};    

try
{
...
}
catch (ExceptionTypeA ex) { handler(ex); }
catch (ExceptionTypeB ex) { handler(ex); }
catch (ExceptionTypeC ex) { handler(ex); }

Ответ 6

Вы бы получили TypeA, B, C из общего базового класса, если это разумно. И поймаем исключение базового класса.

Ответ 7

Не чистый путь. Вы можете просто поймать System.Exception, а затем проверить тип во время выполнения, т.е.

try
{
...
}
catch (System.Exception ex)
{
   if (ex is ExceptionTypeA or ExceptionTypeB or ExceptionTypeC)
   {
       ... same code ...
   }
   else
       throw;
}

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

Ответ 8

Если у вас есть доступ к коду, который определяет пользовательские исключения, одно из возможных решений:

Создайте настраиваемый тип исключения.

public abstract class CustomException : Exception
{
        //Do some stuff here
}

Затем сделайте все свои пользовательские исключения из этого базового типа:

public class MyException1 : CustomException
{
        // Do some stuff here
}

public class MyException2 : CustomException
{
    // Do some stuff here
}

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

try
{
     //Do something that throws a custom exception
}
catch (CustomException ex)
{
     // Do some shared behavior for all the custom exceptions
}