什么类型的异常时要使用一个属性不能为空?时要、为空、属性、异常

2023-09-03 02:19:15 作者:云柯

在我的应用程序需要的,如果一个特定类的属性为null或空抛出异常(如果它是一个字符串)。我不知道什么是在这种情况下,用最好的例外。我不想创建一个新的异常,我不知道ArgumentNullException为宜在这种情况下。

我应该创建一个新的异常或有例外,我可以使用吗?

我不介意抛出ApplicationException。

解决方案

有关标准异常的 MSDN指南规定:

  

执行使用价值的财产的内含价值参数的名称   制定者。

     

下面code例子显示了   物业抛出一个异常,如果   调用者传递一个空参数。

 公共ip地址地址
{
    得到
    {
        退货地址;
    }
    组
    {
        如果(价值== NULL)
        {
            抛出新ArgumentNullException(价值);
        }
        地址=价值;
    }
}
 
畅信达呼叫中心高可用方案保障客服业务持续稳定

此外,对于物业的设计 MSDN指南说:

  

避免从抛出异常   物业干将。

     

属性的getter应该是简单   操作没有任何preconditions。   如果一个getter可能会抛出异常,   考虑重新设计的属性   是一个方法。本建议书   不适用于索引。索引器可以   扔的,因为无效的例外   参数。

     

这是有效的和可以接受的投   例外的从属性setter。

于是抛出 ArgumentNullException 的制定者,而的ArgumentException 的空字符串,什么事都不做,在吸气。由于二传罚球,只有你可以访问支持字段,它很容易,以确保它不包含无效值。具有吸气掷然后毫无意义。然而,这可能是一个好去处使用Debug.Assert.

如果你真的不能提供适当的默认的话,我想你有三种选择:

刚返回无论是在性能和​​文档这种行为作为使用合同的一部分。让来电处理。您可能还需要在构造一个有效的价值。这可能是完全不恰当的,虽然您的应用程序。

替换财产的方法:当传递一个无效的值,它抛出一个setter方法​​,并抛出一个getter方法​​ InvalidOperationException异常当地产从未分配有效值。

投掷 InvalidOperationException异常从吸气,你可以考虑财产从来没有被赋予无效状态。虽然你不应该从正常干将扔,我想这可能是一个很好的理由,使一个例外。

如果您选择选项2或3,您还应该包括TryGet-方法,该方法返回一个布尔这表明如果属性被设置为一个有效的值,如果是返回一个的值超出参数。否则,你强制来电者是ppared处理$ P $的 InvalidOperationException异常,除非他们有previously设置属性本身,从而知道它会不会抛出。比较 int.Parse int.TryParse

我建议使用选项2的TryGet方法。它没有违反任何准则,并规定了调用code的最低要求。

关于其他建议 ApplicationException的是太一般。 的ArgumentException 是有点太笼统了,但罚款,否则。 MSDN文档一次:

  

不要抛出最具体的(最派生)的例外是   适当。例如,如果一个方法   接收视觉空(没有   基本)的说法,它应该抛出   System.ArgumentNullException代替   其基本类型   System.ArgumentException。

事实上,你不应该使用 ApplicationException的在所有(的文档):

  

不要从T派生自定义异常:System.Exception类,而不是T:。System.ApplicationException类

     

这是原本以为自定义异常应派生自ApplicationException的类;然而,这并没有被发现添加显著值。欲了解更多信息,请参阅最佳实践处理异常。

出现InvalidOperationException 意图不是时的参数的方法或属性是无效的,但因为当操作的作为一个整体是无效的( 文档)。它不应该被从设定器抛出:

  

如果在不适当的状态下不要抛出System.InvalidOperationException异常。如果一个属性设置System.InvalidOperationException应该抛出或方法调用不恰当的,因为该对象的当前状态。例如,写入已打开阅读应该抛出一个System.InvalidOperationException异常一个System.IO.FileStream。

顺便说一句, InvalidOperationException异常是当操作是无效的为对象的当前状态。的如果操作始终是整个类无效,你应该使用NotSupportedException.

In my application I need to throw an exception if a property of a specific class is null or empty (in case it's a string). I'm not sure what is the best exception to use in this case. I would hate to create a new exception and I'm not sure if ArgumentNullException is appropriate in this case.

Should I create a new exception or there's an exception I can use?

I don't mind to throw an ApplicationException.

解决方案

The MSDN guidelines for standard exceptions states:

Do use value for the name of the implicit value parameter of property setters.

The following code example shows a property that throws an exception if the caller passes a null argument.

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

Additionally, the MSDN guidelines for property design say:

Avoid throwing exceptions from property getters.

Property getters should be simple operations without any preconditions. If a getter might throw an exception, consider redesigning the property to be a method. This recommendation does not apply to indexers. Indexers can throw exceptions because of invalid arguments.

It is valid and acceptable to throw exceptions from a property setter.

So throw ArgumentNullException in the setter on null, and ArgumentException on the empty string, and do nothing in the getter. Since the setter throws and only you have access to the backing field, it's easy to make sure it won't contain an invalid value. Having the getter throw is then pointless. This might however be a good spot to use Debug.Assert.

If you really can't provide an appropriate default, then I suppose you have three options:

Just return whatever is in the property and document this behaviour as part of the usage contract. Let the caller deal with it. You might also demand a valid value in the constructor. This might be completely inappropriate for your application though.

Replace the property by methods: A setter method that throws when passed an invalid value, and a getter method that throws InvalidOperationException when the property was never assigned a valid value.

Throw InvalidOperationException from the getter, as you could consider 'property has never been assigned' an invalid state. While you shouldn't normally throw from getters, I suppose this might be a good reason to make an exception.

If you choose options 2 or 3, you should also include a TryGet- method that returns a bool which indicates if the property has been set to a valid value, and if so returns that value in an out parameter. Otherwise you force callers to be prepared to handle an InvalidOperationException, unless they have previously set the property themselves and thus know it won't throw. Compare int.Parse versus int.TryParse.

I'd suggest using option 2 with the TryGet method. It doesn't violate any guidelines and imposes minimal requirements on the calling code.

About the other suggestions ApplicationException is way too general. ArgumentException is a bit too general for null, but fine otherwise. MSDN docs again:

Do throw the most specific (the most derived) exception that is appropriate. For example, if a method receives a null (Nothing in Visual Basic) argument, it should throw System.ArgumentNullException instead of its base type System.ArgumentException.

In fact you shouldn't use ApplicationException at all (docs):

Do derive custom exceptions from the T:System.Exception class rather than the T:System.ApplicationException class.

It was originally thought that custom exceptions should derive from the ApplicationException class; however, this has not been found to add significant value. For more information, see Best Practices for Handling Exceptions.

InvalidOperationException is intended not for when the arguments to a method or property are invalid, but for when the operation as a whole is invalid (docs). It should not be thrown from the setter:

Do throw a System.InvalidOperationException exception if in an inappropriate state. System.InvalidOperationException should be thrown if a property set or a method call is not appropriate given the object's current state. For example, writing to a System.IO.FileStream that has been opened for reading should throw a System.InvalidOperationException exception.

Incidentally, InvalidOperationException is for when the operation is invalid for the object's current state. If the operation is always invalid for the entire class, you should use NotSupportedException.