当一个属性不能为null时使用什么exceptiontypes?

在我的应用程序中,如果特定类的属性为null或空(如果是string),则需要引发exception。 我不确定在这种情况下使用什么是最好的例外。 我讨厌创build一个新的exception,我不确定在这种情况下ArgumentNullException是否合适。

我应该创build一个新的exception还是有我可以使用的exception?

我不介意抛出一个ApplicationException。

MSDN的标准例外指南指出:

请使用值作为属性设置器的隐式值参数的名称。

下面的代码示例显示了一个属性,如果调用者传递一个空参数,则抛出exception。

public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } } 

此外, MSDN的财产devise指导说:

避免从属性获取器中抛出exception。

属性获取者应该是没有任何先决条件的简单操作。 如果一个getter可能抛出一个exception,可以考虑重新devise这个属性作为一个方法。 这个build议不适用于指数。 索引器可能由于无效参数而引发exception。

从属性设置器中抛出exception是有效的和可接受的。

所以在setter上null ArgumentException ,在空string上抛出ArgumentNullException ,并且在getter中不做任何事情。 由于setter抛出,只有你有权访问后台字段,很容易确保它不会包含一个无效的值。 吸取投掷是毫无意义的。 这可能是使用Debug.Assert的好地方。

如果你真的不能提供一个合适的默认值,那么我想你有三个select:

  1. 只要返回属性中的任何内容,并将此行为logging为使用合同的一部分即可。 让调用者处理它。 您可能还需要在构造函数中有效的值。 这可能是完全不适合你的应用程序。

  2. 通过方法replace属性:传递无效值时引发的setter方法,以及当属性从未分配有效值时抛出InvalidOperationException的getter方法。

  3. 从getter抛出InvalidOperationExceptionexception,因为您可能认为“属性从未分配过”无效状态。 虽然你通常不应该从getter中抛出,但我想这可能是个例外的好理由。

如果您select选项2或3,则还应该包含一个TryGet-方法,该方法返回一个bool ,该bool指示该属性是否已设置为有效值,如果是,则返回out参数中的值。 否则,你强制调用者准备处理一个InvalidOperationException ,除非他们之前已经设置了属性,从而知道它不会抛出。 比较int.Parseint.TryParse

我build议使用TryGet方法的选项2。 它不违反任何指导原则,并对调用代码施加最小的要求。


关于其他build议
ApplicationException太泛泛。 ArgumentException对于null有点过于笼统,否则就是罚款。 MSDN文档再次 :

抛出最适合的最具体的(派生的)exception。 例如,如果方法接收到null(Visual Basic中为Nothing)参数,则应抛出System.ArgumentNullException,而不是其基本typesSystem.ArgumentException。

实际上你根本不应该使用ApplicationException ( docs ):

从T:System.Exception类而不是T:System.ApplicationException类派生自定义exception。

最初认为自定义exception应该从ApplicationException类派生; 然而,这并没有被发现增加显着的价值。 有关更多信息,请参阅处理exception的最佳实践。

InvalidOperationException不适用于方法或属性的参数无效时,而是整个操作无效的情况( docs )。 它不应该从二传手抛出:

如果处于不适当的状态,请抛出System.InvalidOperationExceptionexception。 给定对象的当前状态,如果属性集或方法调用不适合,则应引发System.InvalidOperationException。 例如,写入已经打开读取的System.IO.FileStream应该抛出一个System.InvalidOperationExceptionexception。

顺便说一句, InvalidOperationException是当对象的当前状态的操作无效时 如果整个类的操作始终无效,则应该使用NotSupportedException

我会抛出一个InvalidOperationException 。 MSDN说这是“当一个方法调用对象的当前状态无效时抛出”。

那么,如果你正在引用一个类的属性,这不是一个参数。 所以,你不应该使用ArgumentException或ArgumentNullException。

NullReferenceException会发生,如果你只是把事情放在一边,所以我认为这不是你在找什么。

所以,使用ApplicationExeption或InvalidOperationException可能是您最好的select,确保给出一个有意义的string来描述错误。

抛出ArgumentNullException是非常合适的,如果有人试图分配 null。

一个属性不应该抛出一个读取操作。

构造函数是否将其设置为非空值? 如果是这样,我只会从setter中抛出ArgumentNullException

如果问题是一个参数的成员,而不是参数本身,是空的,那么我认为最好的select是更通用的ArgumentExceptionArgumentNullException在这里不起作用,因为参数实际上不是null。 相反,你需要更通用的“你的论点是错误的”exceptiontypes。

这里的构造函数的详细消息将是非常合适的

如果它不能为null或空,那么让你的setter不允许null或空值,或者如果是这样的话就抛出一个ArgumentException。

另外,要求在构造函数中设置该属性。

这样你强制一个有效的价值,而不是稍后回来,说你不能确定账户余额,因为没有设置帐户。

但是,我同意bduke的回应。

有一个将ArgumentNullException的解释扩展为意义“string参数为null或空”的先例:在这种情况下,System.Windows.Clipboard.SetText将引发一个ArgumentNullException。

所以我不会看到在你的属性设置器中使用这个而不是更通用的ArgumentException的任何错误,只要你logging它。

只要抛出错误信息对开发人员有帮助即可。 无论如何,这类例外不应该发生在开发之外。