我正在查看一些旧代码,很好奇在setter属性中包含逻辑是否合适,或者是否有更好的书写方式,为什么?谢谢!
string qBankCode;
string qCode;
public string QBankCode
{
get => qBankCode;
set
{
if (value.Length == 0)
throw new ArgumentException("You need to enter the question bank code as it is mandatory.");
if (value.Length > 30)
throw new ArgumentException("Question bank code cannot exceed 30 characters.");
qBankCode = value;
}
}
public string QCode
{
get => qCode;
set
{
if (value.Length == 0)
throw new ArgumentException("You need to enter the question code as it is mandatory.");
if (value.Length > 30)
throw new ArgumentException("Question code cannot exceed 30 characters.");
qCode = value;
}
}
答案 0 :(得分:4)
根据Framework Design Guidelines:
二传手可以抛出异常
✓如果属性设置器引发异常,请保留先前的值。
✓不要允许以任何顺序设置属性,即使这会导致对象暂时处于无效状态。
只要它们不依赖于其他属性的状态,例如
public string QCode
{ ... set {...
if (QBankCode.Length ==10 && value.Length % 2 == 0)
throw new exception();...
您的代码示例符合此要求,但您应确保属性具有合理的默认值
✓不要为所有属性提供合理的默认值,...
答案 1 :(得分:2)
我认为在属性设置器中使用逻辑通常并不可行,但是您的示例显示了 validation ,这不仅可以,而且是一种很好的做法。
或者如果有更好的方法来编写此代码,为什么?
确实取决于代码的使用方式。
例如,对于MVC或EntityFramework模型,人们可以争辩StringLength
和Required
属性。请参阅Adding Validation to the Model (C#)或StringLengthAttribute Class 。
如果确实很重要,则应在多个级别上进行验证(抛出和 use属性)。
请注意,属性需要框架(MVC,EF等)来强制执行,而throw new ArgumentException
在所有情况下都可以使用,这可能是理想的选择。
请注意,异常在库的构建版本中不可见,并且如果您的模型以二进制形式分发,则通过其他方式传达验证规则非常重要。
请注意,虽然验证异常可以确保在必须支持多种语言或允许在不部署新代码的情况下更改消息的情况下阻止不良值,但是您必须提出一些其他方法来处理验证失败。
Microsoft的Property Design .NET指南指出
✓不要允许以任何顺序设置属性,即使这会导致对象暂时处于无效状态。
在同一个对象上给定其他属性值的情况下,一个属性的某些值可能无效的点通常与两个或多个属性相互关联。在这种情况下,无效状态引起的异常应推迟到对象实际一起使用相互关联的属性为止。
我非常不同意这种设计,但是像往常一样,在某些情况下它是有意义的。
我发现将对象保持在有效状态的系统更易于使用,并且我总是首先鼓励不变的类设计。