c# - 使用内部异常或创建基本异常的派生类型
问题描述
如果有一个方法调用了许多其他方法并且它们都可以抛出从 ArgumentExceptions 到 EndOfStreamExceptions 的各种异常,最好做一个 catch all 并将其包装在您自己的异常中,然后设置内部异常,或者创建一个基类异常和抛出派生类型。如果抛出违反尽可能重用 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,然后,如果需要更多详细信息,请切换到以下选项 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 中具有特定于 DoSomething 的异常逻辑,而不是分散在您的辅助方法周围,这些方法可以使用“自然”BCL 执行。
推荐阅读
- mongodb - MongoDB 枚举一个键的所有数据类型
- php - 我的 Vue.js 代码在加载时不工作
- android - 在 NestedScrollview 中带有 HasFixedSize 的 Recyclerview wrap_content 不显示项目
- php - 使用 Carbon 延迟作业调度时出现意外的“->”
- migradoc - MigraDoc 将页脚文本框绝对定位到页面底部边缘
- c++ - OpenGL 纹理状态使用警告:
- python - x 和 y 必须具有相同的第一维,但具有形状 (1,) 和 (6,)
- php - 试图在被覆盖的部分刀片中获取非对象的属性“名称”
- javascript - 计数器应重置为零,然后再次从 1 开始
- javascript - 数组中的 findOneAndUpdate 嵌套对象