c# - .NET 返回值与抛出的异常设计问题

标签 c# .net exception-handling return-value

假设我们有一个方法处理树状分层数据结构中的操作,该数据结构位于处理此类结构的类中。

让我们仔细看看其中一种方法:

void MoveNode(Node currentNode, Node newParentNode)
{
    /* check if new parent isn't current's child already */
     if (newParentNode.LMargin < currentNode.LMargin && newParentNode.RMargin > currentNode.RMargin)
     {
        //DO WORK
     }
     else throw new ArgumentException("New parent node cannot be current's own child");
}

MSDN 声明:不要抛出异常来控制流程!

我的问题:您认为这种 ArgumentException 的使用是否合适,或者您会使用某种返回值。 如果是这样,您将如何提供错误/验证消息。

最佳答案

由于抛出的异常表明此处存在错误,因此在正常工作的程序中永远不会抛出异常,因此异常是正确的选择。

你不应该做的是:

try
{
   MoveNode(...)
   //Do something
}
catch(ArgumentException e)
{
  //Do something else
}

在该示例中,您希望定期抛出异常并使用它来控制控制流。在调用者中捕获 ArgumentException 几乎总是一个坏主意。这种异常应该只在顶级处理程序中捕获,如果有的话。

我个人不喜欢在 else 子句中抛出异常。我更喜欢在函数开始时进行参数检查,然后立即抛出异常。这可以防止在多个 if block 中嵌套非错误代码。

异常分为三种

  1. 异步异常,如 StackOverflow、OutOfMemory 和 ThreadAborted。它们可能发生在任何地方,而且无法真正处理
  2. 错误异常,如 ArgumentException,将它们记录在顶级处理程序中并修复错误
  3. 预期的异常指示可以在本地处理的错误。通常,当错误不常见并且您无法事先知道某个操作会导致错误时,您会使用这些。 IO错误就是一个典型的例子。
    原因通常是外部的。例如无法访问的文件、网络故障或您尝试解析的文件中的无效数据。

Eric Lippert 在博客条目中讨论了这些类型的异常:Vexing exceptions

什么时候用第三种异常,什么时候用返回值是判断调用。

关于c# - .NET 返回值与抛出的异常设计问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4884539/

相关文章:

c# - 如何创建其他可观察集合的可观察集合? MVVM 模式

c# - 删除 wpf datagrid 上的所有边框

exception - Grails 2.2.4最佳实践中具有ExceptionMapper的Grails Controller 中的异常处理

c# - 异步功能内的错误处理

c# - Entity Framework 6 中存储过程的执行是否需要调用 SaveChanges?

C# 注册嵌入式 Directshow 过滤器

c# - 获取音频缓冲区数据

c# - 从 Excel VBA 调用未注册的 .NET dll

c# - 让我的 userControl 在工具箱上有自己的图标

c# - 如何在单元测试中模拟在随机代码点抛出异常?