关于c#:尝试在集合中插入重复对象时抛出的正确.NET异常是什么?

关于c#:尝试在集合中插入重复对象时抛出的正确.NET异常是什么?

What is the correct .NET exception to throw when try to insert a duplicate object into a collection?

我有一个Asset对象,该对象具有一个属性AssignedSoftware,它是一个集合。

我想确保同一软件不能多次分配给资产。在添加方法中,我检查该软件是否已经存在,如果存在,我想抛出一个异常。

我应该抛出一个标准的.NET异常吗?还是最佳实践指示我创建自己的自定义异常?


为什么InvalidOperationException被接受为答案?!它应该是ArgumentException?!

如果具有调用的方法/属性的对象由于未初始化状态等而无法处理请求,则应使用

InvalidOperationException。这里的问题不是对象被添加到,而是对象被传递给对象(这是一个骗子)。考虑一下,如果从未执行过此Add调用,则该对象是否仍将正常运行,是!

这应该是ArgumentException。


如果您尝试两次将具有相同键值的项添加到哈希表中,则

.Net将引发System.ArgumentException,因此看起来没有更具体的内容。如果需要更具体的信息,则可能需要编写自己的异常。


有关错误的类库设计准则(http://msdn.microsoft.com/zh-cn/library/8ey5ey87(VS.71).aspx):

In most cases, use the predefined exception types. Only define new exception types for programmatic scenarios, where you expect users of your class library to catch exceptions of this new type and perform a programmatic action based on the exception type itself. This is in lieu of parsing the exception string, which would negatively impact performance and maintenance.

...

Throw an ArgumentException or create an exception derived from this class if invalid parameters are passed or detected.

Throw the InvalidOperationException exception if a call to a property set accessor or method is not appropriate given the object's current state.

在我看来,这是一个"对象状态无效"的情况,因此我选择InvalidOperationException而不是ArgumentException:参数是有效的,但此时在对象生命周期中不起作用。


您可能应该抛出ArgumentException,因为这就是基础库类所做的。


好吧,如果您真的想要一个包含唯一项的集合,则可能需要看一下HashSet对象(在C#3.0中可用)。

否则,您可以采用两种方法:

  • 就像您所说的那样,为您的操作创建一个自定义异常
  • 实现一个Add()方法,该方法返回一个布尔结果:如果添加了该项目,则返回true;如果该项目在集合中已经具有重复项,则返回false。

只要您的用法一致,就可以将这两种方法都视为最佳实践。


推荐阅读