在我的应用程序中,如果特定类的属性为null或为空(如果它是字符串),则需要抛出异常。我不确定在这种情况下使用的最佳例外是什么。我不想创建一个新的异常,我不确定在这种情况下ArgumentNullException是否合适。
我应该创建一个新的例外还是我可以使用的例外?
我不介意抛出一个ApplicationException。
答案 0 :(得分:68)
MSDN guidelines for standard exceptions州:
使用value作为property的隐式value参数的名称 setter方法。强>
以下代码示例显示了一个 如果抛出异常的属性 调用者传递一个null参数。
public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } }
此外,MSDN guidelines for property design说:
避免抛出异常 财产获取者。
属性getter应该很简单 没有任何先决条件的操作。 如果getter可能抛出异常, 考虑重新设计财产 是一种方法。这个建议有 不适用于索引器。索引器可以 由于无效而抛出异常 参数。
投掷是有效和可接受的 来自属性设置器的异常。
所以在ArgumentNullException
上的setter中抛出null
,在空字符串上抛出ArgumentException
,并在getter中不执行任何操作。由于setter抛出并且只有您可以访问支持字段,因此很容易确保它不包含无效值。获得吸气剂是没有意义的。但这可能是使用Debug.Assert
的好地方。
如果你真的无法提供适当的默认值,那么我想你有三个选择:
只需返回属性中的内容,并将此行为记录为使用合同的一部分。让呼叫者处理它。您可能还需要构造函数中的有效值。这可能完全不适合您的应用程序。
通过方法替换属性:在传递无效值时抛出的setter方法,以及在从未为属性指定有效值时抛出InvalidOperationException
的getter方法。
从getter中抛出InvalidOperationException
,因为您可以认为'属性从未被分配'为无效状态。虽然你通常不应该从吸气剂中扔掉,但我认为这可能是做出例外的一个很好的理由。
如果选择选项2或3,则还应包括一个TryGet-方法,该方法返回bool
,指示属性是否已设置为有效值,如果是,则返回{{1}中的值。 1}}参数。否则,强制调用者准备处理out
,除非他们先前已经设置了属性,因此知道它不会抛出。比较InvalidOperationException
与int.Parse
。
我建议在TryGet方法中使用选项2。它不违反任何指导原则,并对调用代码施加最低要求。
关于其他建议
int.TryParse
过于笼统。对于ApplicationException
,ArgumentException
有点过于笼统,但不然如此。 MSDN docs again:
抛出最具体(最派生)的异常 适当。例如,如果一个方法 收到一个null(在Visual中没有 基本的)论证,它应该抛出 而是System.ArgumentNullException 它的基本类型 System.ArgumentException 强>
事实上,你根本不应该使用null
(docs):
从T:System.Exception类派生自定义异常,而不是T:System.ApplicationException类。
最初认为自定义异常应该来自ApplicationException类;然而,这并未发现增加显着价值。有关更多信息,请参阅处理异常的最佳实践。
ApplicationException
不适用于方法或属性的参数无效,但是当操作整体无效时(docs)。它不应该被设置者抛出:
如果处于不适当的状态,则抛出System.InvalidOperationException异常。如果在给定对象的当前状态的情况下属性集或方法调用不合适,则应抛出System.InvalidOperationException。例如,写入已打开以供读取的System.IO.FileStream应抛出System.InvalidOperationException异常。
顺便提一下,InvalidOperationException
适用于对象当前状态的操作无效。如果整个类的操作始终无效,则应使用NotSupportedException
。
答案 1 :(得分:4)
我会抛出InvalidOperationException
。 MSDN称,当方法调用对于对象的当前状态无效时,它会被抛出。“
答案 2 :(得分:2)
嗯,如果你引用了一个类的属性,它不是一个参数。因此,您不应该使用ArgumentException或ArgumentNullException。
如果你只是把事情单独留下就会发生NullReferenceException,所以我认为这不是你想要的。
因此,使用ApplicationExeption或InvalidOperationException可能是您最好的选择,请确保提供有意义的字符串来描述错误。
答案 3 :(得分:2)
如果有人试图指定 null,则抛出ArgumentNullException非常合适。
属性不应该抛出读操作。
答案 4 :(得分:1)
构造函数是否将其设置为非null值?如果是这样,我只会从设置器中抛出ArgumentNullException
。
答案 5 :(得分:1)
如果问题是参数的成员而不是参数本身是null,那么我认为最好的选择是更通用的ArgumentException
。 ArgumentNullException
在这里不起作用,因为参数实际上不是null。相反,你需要更通用的“你的论点有问题”的异常类型。
构造函数的详细消息在这里非常合适
答案 6 :(得分:1)
如果它不能为null或为空,请让你的setter不允许null或空值,否则抛出ArgumentException。
另外,要求在构造函数中设置属性。
通过这种方式,您可以强制使用有效值,而不是稍后返回并说明由于未设置帐户而无法确定帐户余额。
但是,我同意bduke的回应。
答案 7 :(得分:1)
有一个先例可以将ArgumentNullException的解释扩展为“字符串参数为null或为空”:在这种情况下,System.Windows.Clipboard.SetText将抛出ArgumentNullException。
因此,如果你记录它,我会发现在你的属性设置器中使用它而不是更一般的ArgumentException有什么问题。
答案 8 :(得分:0)