.net - 什么时候是抛出 InvalidOperationException 的好时机?

标签 .net exception throw invalidoperationexception

我想我知道我的意思,但我不太确定......

Framework 文档总结了该类型如下:

The exception that is thrown when a method call is invalid for the object's current state.



有明确的情况,我想到的情况是当操作需要打开数据库但对象尚未使用连接到数据库所需的信息进行初始化时。

(切线:另一方面,ADO.NET 还要求您显式打开连接的行为并不那么明确;DataAdapter 通过简单地打开连接 instad 与此背道而驰,当且仅当它关闭时再次关闭它条目,我发现这很方便,并让自己成为一个 ADO.NET 包装器,该包装器对所有内容都使用此模式。当然,这意味着我冒着执行 2 ExecuteNonQuery 并不必要地将连接返回到两者之间的池的风险,但我仍然可以打开和关闭与获得异常相比,我想要的连接和这种性能损失算不了什么。)

我想我的问题的答案是,只有在这种明确的情况下,我们才应该抛出异常。但是在以下场景中哪种异常类型最合适:
public class FormatterMapping
{
  Dictionary formattersByName = new ...();

  public IFormatter GetFormatter(string key) 
  {
     IFormatter f;
     if (formattersByName.TryGetValue(key, out f)) 
       return f;
     else
       throw new ??Exception("explanation of why this failed.");
  }
}

我的第一 react 是抛出 ArgumentException。然后我开始认为映射缺少一个键也可能与参数“错误”一样。基本上“获取格式化程序 X”操作是无效的,因为 X 不在映射中,但我真的不知道 X 是否“应该在那里”或者在这里要求 X 是不明智的。

我当然可以通过返回 null 来规避整个问题,但这会打开一个更大、更深的蠕虫 jar 头。没有办法知道什么时候会使用返回值,所以稍后因 NullReferenceException 而爆炸的代码可能与出错的地方没有明显的关系。要么映射设置不当,要么使用它的代码要求一些不应该的东西。

避免该问题的另一种方法是使用 TryGetFormatter 选项,但我打算使用它的方式实际上调用者应该知道映射中的内容和不包含的内容,因此在用户代码上强制使用此模式不是也不错。

请不要回答我应该抛出 ApplicationException!无论您认为代码应该做什么,请提供原因。毕竟,这里真正有问题的是推理。

除非有人说服我,否则我倾向于 ArgumentException。从映射的角度来看,这个论点是错误的,所以至少有一个明确的推理支持这一点。 :)

最佳答案

两者都不是完美的,两者都很好。或者,也许你想要一些真正明确的东西:

KeyNotFoundException .

public class FormatterMapping
{
    Dictionary<string, IFormatter> formattersByName = new ...();

    public IFormatter GetFormatter(string key) 
    {
        // validate the argument
        if (!formattersByName.ContainsKey(key))
            throw new KeyNotFoundException("No formatter exists for given key");

        return formattersByName[key];
    }
}

或者,您可以让 Dictionary<> 扔掉它。

我建议你选择一个,记录下来然后继续。通常不值得浪费大量时间来选择要抛出的特定异常。记录行为更为重要。

关于.net - 什么时候是抛出 InvalidOperationException 的好时机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9467033/

相关文章:

.net - GAC Scope : why does it override local assemblies, 有什么我们可以做的吗?

haskell - 在 Haskell 中执行一系列操作时的异常处理

php - 将异常抛出到下一个 Catch block

c# - 总是 try catch 外部资源调用?

c++ - 单个 "throw;"语句有什么作用?

c# - 抛出 VS 重新抛出 : same result?

c# - MSChart 控件中的自定义 X/Y 网格线

.net - 从 ToolStripPanel 中取消停靠 ToolStrip

c# - 替换 NUnit 中的 Console.WriteLine

c++ - GoogleTest:EXPECT_THROW 捕获不同的类型?