尝试向集合中插入重复对象时抛出的正确.NET异常是什么?
我有一个Asset对象,该对象具有一个属性AssignedSoftware,它是一个集合。
我想确保同一软件不能多次分配给资产。在添加方法中,我检查该软件是否已经存在,如果存在,我想抛出一个异常。
我应该抛出一个标准的.NET异常吗?还是最佳实践指示我创建自己的自定义例外?
解决方案
回答
我们可能应该抛出ArgumentException,因为这是基库类所做的。
回答
好吧,如果我们真的想要一个包含唯一项的集合,则可能需要看一下HashSet对象(在C3.0中可用)。
否则,可以采用两种方法:
- 就像我们所说的那样,为操作创建一个自定义异常
- 实现一个Add()方法,该方法返回一个布尔结果:如果添加了该项目,则返回true;如果该项目在集合中已经具有重复项,则返回false。
只要我们使用一致,则可以将这两种方法都视为最佳实践。
回答
我一直喜欢InvalidOperationException。但是,我们也可以创建一个自定义异常,例如DuplicateSoftwareAssignmentException。
根据框架设计指南:
"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."
当前状态包括对其他类实例的引用。在这种情况下,状态已经包括对要添加的实例的引用,因此对该方法的调用是不合适的。
回答
如果我们尝试两次将具有相同键值的项添加到哈希表中,则.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:参数是有效的,但此时在对象生命周期中无效。
回答
为什么IOE被接受为答案?!它应该是ArgumentException吗?
如果由于未初始化状态等原因而调用了方法/属性的对象无法处理请求,则应使用IOE。这里的问题不是对象被添加到对象,而是对象被传递给对象(是骗子)。考虑一下,如果从未执行过此Add调用,则该对象是否仍将正常运行,是!
这应该是ArgumentException。