С# Обработка исключений
Возможный дубликат:
Захват нескольких Исключений сразу?
Есть ли какой-либо способ в С#, чтобы легко достичь следующего 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
}