我想我知道我的意思但我不太确定......
框架文档总结了如下类型:
当方法调用对象的当前状态无效时引发的异常。
有明确的案例,想到的是一个操作需要一个开放的数据库,但该对象尚未初始化所需的信息以连接到数据库。
(Tangent:另一方面也要求你明确打开连接的ADO.NETs行为并不是那么明确; 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.");
}
}
我的第一直觉是抛出ArgumentException。然后我开始认为,由于参数“错误”,映射缺少一个键也可能。基本上“获取格式化程序X”操作无效因为 X不在映射中,但我真的不知道X“是否应该在那里”或者要求它是不明智的X在这里。
我当然可以通过返回null来绕过整个问题,但这会打开更大,更深的蠕虫。没有办法知道何时使用返回值,因此稍后用NullReferenceException抛出的代码可能与出错的地方没有明显的关系。要么映射设置不当,要么使用它的代码要求它不应该。
避免这个问题的另一种方法是前往TryGetFormatter选项,但我打算使用它的方式实际上应该知道调用者是什么和不在映射中,所以强迫用户使用这种模式代码也不好。
请不要回答我应该抛出ApplicationException!无论您认为代码应该做什么,请提供原因。毕竟这是在这里真正存在问题的推理。
除非有人说服我,否则我倾向于ArgumentException。从映射的角度来看,论证是错误的,所以至少有一条明确的推理线支持这一点。 :)
答案 0 :(得分:4)
两者都不完美,两者都没问题。或许你想要一些真正明确的东西:
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&lt;&gt;抛出它。
我建议您选择一个,记录并继续。通常不值得浪费大量时间选择特定的例外情况。记录行为更为重要。
答案 1 :(得分:3)
我会考虑使用ArgumentException
来代替这样的事情:
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Expected a key");
}
对于您的示例,我认为InvalidOperationException
或KeyNotFoundException
适合,或者如果您认为合适,只需编写自己的。
纯粹主义者可能不喜欢我的观点,但我的例外情况会在我工作的系统中自动通过电子邮件发送给我,所以最终在大多数情况下我并不关心我抓到的异常 type 只要我能从中获得足够的有用信息,看看发生了什么。这包括: