我有一个字符串属性,它具有最大长度要求,因为数据链接到数据库。如果调用者试图设置超过这个长度的字符串,我应该抛出什么异常?
例如,这个C#代码:
public string MyProperty
{
get
{
return _MyBackingField;
}
set
{
if (value.Length > 100)
throw new FooException("MyProperty has a maximum length of 100.");
_MyBackingField = value;
}
}
我考虑过ArgumentException
,但这似乎不对。 技术上,它是一个函数 - MyProperty_set(string value)
- 因此ArgumentException
的情况可以被制作,但它不是作为消费者眼睛的函数调用的 - 它在右边赋值运算符的一面。
这个问题可能还可以扩展到包括在属性设置器中完成的各种数据验证,但我对上述情况特别感兴趣。
答案 0 :(得分:46)
通过使用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
}
}
答案 1 :(得分:16)
对我来说ArgumentException(或child)更有意义,因为你提供的参数(value)无效,这就是为它创建的ArgumentException。
答案 2 :(得分:10)
我根本不会抛出异常。相反,我会允许任意长度的字符串,然后在保存之前调用的类上有一个单独的“Validate”方法。有很多场景特别是如果你使用数据绑定,从属性设置器中抛出异常会让你陷入混乱。
从属性设置器中抛出异常的麻烦是程序员忘记捕获它们。这取决于您对预期数据的清洁程度。在这种情况下,我希望长字符串长度是常见的而不是例外,因此使用异常将是“具有异常的流量控制”。
引用微软的Design Guidelines for Developing Class Libraries:
不要将异常用于正常流程 控制,如果可能的话。除了 系统故障和操作 潜在的竞争条件,框架 设计师应该设计API 用户可以编写没有的代码 抛出异常。例如,你可以 提供检查前提条件的方法 在呼叫成员以便用户之前 可以编写不抛出的代码 异常。
答案 3 :(得分:6)
还记得通过增加一个额外的间接层来解决计算机科学中有多少问题?
一种方法是创建一个新类型,FixedLengthString,比方说。它将是 类型的实例,它验证它们初始化的字符串长度 - 使用转换运算符从普通字符串进行类型转换。如果属性setter采用这种类型作为其参数,则任何违规都将成为类型转换异常,而不是参数/属性异常。
在实践中,我很少会这样做。它闻起来有点过分了OO - 但在某些情况下它可能是一种有用的技术,所以我在这里提到完整性。
答案 4 :(得分:5)
public IPAddress Address
{
get
{
return address;
}
set
{
if(value == null)
{
throw new ArgumentNullException("value");
}
address = value;
}
}
通过MSDN
答案 5 :(得分:-1)
您可以使用InvalidOperationException。这是妥协。我也不打算使用ArgumentException。
答案 6 :(得分:-2)
尝试尽可能使用现有的例外情况。在这种情况下,使用InvalidOperationException,因为传入的值使对象处于不一致状态。当需要使用自定义异常进行特定处理时,可以创建自定义异常。在这种情况下,您只抛出一些带有文本的异常,因此请使用InvalidOperationException。
抛出InvalidOperationException时显示已传递给此setter的值。