#c# #exception
Вопрос:
В тех случаях, когда есть метод, который вызывает множество других, и все они могут создавать различные исключения от ArgumentExceptions до EndOfStreamExceptions, было бы лучше выполнить перехват всех и обернуть его в свое собственное исключение, а затем установить внутреннее исключение или создать исключение базового класса и создать производные типы. Если выбрасывание производных типов противоречит рекомендациям по повторному использованию исключений BCL, где это возможно. Так, например
public void A()
{
if (someCondition)
{
throw new ArgumentException()
}
}
public void B()
{
if (anotherCondition)
{
throw new InvalidOperation()
}
}
public void C()
{
// Throws format exception
int.Parse(x);
}
public void DoSomething()
{
try
{
A();
B();
C();
}
catch(Exception ex)
{
throw new DoSomethingException("Could not complete DoSomthing"){ InnerException = ex};
}
}
ИЛИ было бы лучше сделать что-то вроде
public void DoSomething()
{
A();
B();
C();
D();
}
public void A()
{
if (someCondition)
{
throw new DoSomethingMissingArg()
}
}
public void B()
{
if (anotherCondition)
{
throw new DoSomethingCannotStart()
}
}
public void C()
{
// Throws format exception
if (!int.TryParse(x))
{
throw new DoSomethingFormatException("x must be in y format");
}
}
public class DoSomethingException: Exception
{
}
public class DoSomethingMissingArg: DoSomethingException
{
public DoSomethingMissingArg(){ }
}
public class DoSomethingCannotStart: DoSomethingException
{
public DoSomethingCannotStart(){ }
}
public class DoSomethingFormatException: DoSomethingException
{
public DoSomethingFormatException(){ }
}
Ответ №1:
Это просто зависит от того, потребуется ли вашим абонентам такой уровень детализации при обнаружении ваших исключений.
Мое предложение состояло бы в том, чтобы сначала реализовать вариант 1, а затем, если требуется более подробная информация, переключиться на следующий вариант 3:
public void A()
{
if (someCondition)
{
throw new ArgumentException()
}
}
...
public void DoSomething()
{
try
{
A();
}
catch(ArgumentException ex)
{
throw new DoSomethingMissingArgException() { InnerException = ex };
}
try
{
B();
C();
}
catch(Exception ex)
{
throw new DoSomethingException("Could not complete DoSomthing"){ InnerException = ex};
}
}
Вариант 3 имеет следующие преимущества:
- Это обратно совместимо с вариантом 1, так как исключение DoSomethingMissingArgException является исключением DoSomethingException. И вы можете добавлять дополнительные подклассы исключений по мере необходимости, сохраняя при этом обратную совместимость.
- У вас есть логика исключений, зависящая от конкретного способа, только в методе doSomething, а не разбросанная вокруг ваших вспомогательных методов, которые могут использовать «естественные» исполнительные функции BCL.