C# 从属性设置器抛出什么异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/633944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What exception to throw from a property setter?
提问by lc.
I have a string property that has a maximum length requirement because the data is linked to a database. What exception should I throw if the caller tries to set a string exceeding this length?
我有一个具有最大长度要求的字符串属性,因为数据链接到数据库。如果调用者尝试设置超过此长度的字符串,我应该抛出什么异常?
For example, this C# code:
例如,这个 C# 代码:
public string MyProperty
{
get
{
return _MyBackingField;
}
set
{
if (value.Length > 100)
throw new FooException("MyProperty has a maximum length of 100.");
_MyBackingField = value;
}
}
I considered ArgumentException
, but it just doesn't seem right. Technically, it is a function - MyProperty_set(string value)
- so a case for ArgumentException
can be made, but it's not being called as a function to the consumer's eyes - it's on the right side of an assignment operator.
我考虑过ArgumentException
,但似乎不太对。从技术上讲,它是一个函数——MyProperty_set(string value)
所以ArgumentException
可以提出一个案例,但它不会被消费者视为函数——它位于赋值运算符的右侧。
This question could probably also be extended to include all kinds of data validation done in property setters, but I'm particularly interested in the above case.
这个问题可能也可以扩展到包括在属性设置器中完成的各种数据验证,但我对上述案例特别感兴趣。
采纳答案by Richard Slater
Have a look through mscorlib.dll with Reflector, in a similar situation such as System.String.StringBuilder.Capacity Microsoft use ArgumentOutOfRangeException() similar to:
用 Reflector 查看 mscorlib.dll,在类似的情况下,例如 System.String.StringBuilder.Capacity Microsoft 使用 ArgumentOutOfRangeException() 类似于:
public int PropertyA
{
get
{
return //etc...
}
set
{
if (condition == true)
{
throw new ArgumentOutOfRangeException("value", "/* etc... */");
}
// ... etc
}
}
回答by Sascha
You may use InvalidOperationException. That's a compromise. I wouldn't bother using an ArgumentException either.
您可以使用 InvalidOperationException。那是一种妥协。我也不会费心使用 ArgumentException。
回答by Davide Vosti
To me ArgumentException (or a child) makes more sense, because the argument (value) you provided is not valid, and this is what ArgumentException was created for.
对我来说 ArgumentException (或孩子)更有意义,因为您提供的参数(值)无效,这就是 ArgumentException 的创建目的。
回答by Martin Brown
I wouldn't throw an exception at all. Rather I would allow a string of any length and then have a seperate "Validate" method on the class that is called before saving. There are a number of scenarios particularly if you use databinding where throwing exceptions from property setters can get you in a mess.
我根本不会抛出异常。相反,我会允许任何长度的字符串,然后在保存之前调用的类上有一个单独的“验证”方法。有很多场景,特别是如果您使用数据绑定,从属性设置器抛出异常可能会让您陷入困境。
The trouble with throwing exceptions from property setters is that programmers forget to catch them. It kind of depends upon how clean you expect the data you are getting to be. In this case I would expect long string lengths to be common not exceptional and as such using an exception would be "flow control with exceptions".
从属性设置器抛出异常的麻烦在于程序员忘记捕捉它们。这在某种程度上取决于您期望获得的数据有多干净。在这种情况下,我希望长字符串长度是常见的而不是异常的,因此使用异常将是“带有异常的流控制”。
To quote from the Microsoft's Design Guidelines for Developing Class Libraries:
Do not use exceptions for normal flow of control, if possible. Except for system failures and operations with potential race conditions, framework designers should design APIs so that users can write code that does not throw exceptions. For example, you can provide a way to check preconditions before calling a member so that users can write code that does not throw exceptions.
如果可能,不要将异常用于正常的控制流。除了系统故障和具有潜在竞争条件的操作外,框架设计者应该设计 API,以便用户可以编写不会抛出异常的代码。例如,您可以提供一种在调用成员之前检查前提条件的方法,以便用户可以编写不会引发异常的代码。
回答by philsquared
Remember how many problems in computer science are solved by adding an extra level of indirection?
还记得通过添加额外的间接级别解决了计算机科学中的多少问题吗?
One approach would be to create a new type, FixedLengthString, say. It would be instances of thattype that validate lengths of strings they are initialised with - with a conversion operator to do type conversion from a plain string. If your property setter takes such a type as its argument then any violation would become a type conversion exception instead of an argument/ property exception.
一种方法是创建一个新类型,例如 FixedLengthString。这将是实例是类型,它们被初始化处理字符串的长度验证-一个转换操作符从一个普通字符串做类型转换。如果您的属性设置器采用这样的类型作为其参数,那么任何违规都将成为类型转换异常,而不是参数/属性异常。
In practice I would rarely do this. It smells a bit of taking OO too far - but in some cases it can be a useful technique, so I mention it here for completeness.
在实践中,我很少这样做。它闻起来有点过头了 OO - 但在某些情况下它可能是一种有用的技术,所以我在这里提到它是为了完整性。
回答by Patrick Peters
Try to use existing exceptions whereever possible. In this case use InvalidOperationException because the incoming value is bringing the object in an inconsistent state. Custom exceptions can be created when a specific handling with the custom exception is needed. In this case you only throw an exception with some text, so use the InvalidOperationException.
尽可能尝试使用现有的异常。在这种情况下使用 InvalidOperationException 因为传入的值使对象处于不一致的状态。当需要对自定义异常进行特定处理时,可以创建自定义异常。在这种情况下,您只会抛出带有某些文本的异常,因此请使用 InvalidOperationException。
When throwing the InvalidOperationException show the value that has been passed to this setter.
抛出 InvalidOperationException 时显示已传递给此 setter 的值。