所以我有一个简单的类,User
,就像这样(忽略可怕的空白使用,想让它简要在线阅读):
public class User
{
private string username;
public string Username
{
get
{
return username;
}set{
if(Validate.usernameIsValid(value)){username = value;}
else{throw new InvalidArgumentException("Username is invalid");}
}
}
//some more fields
public User(String argUsername)
{
this.Username = argUsername;
//OR validate again before:
username = argUsername;
}
}
使用类中的公共访问器来使用其验证更好吗?或者这是不好的做法,在这种情况下,我应该在设置私人username
字段之前重新验证吗?
答案 0 :(得分:1)
答案取决于数据的来源。由于使用setter后面的驱动点是为了避免重复验证代码,因此有两个基本情况:
前一种情况延伸到您阅读用户输入的情况。
后一种情况包括从快照恢复对象状态或在内部生成对象状态的情况。例如,如果您的setter具有null
/空字符串验证,并且您的方法想要将字符串设置为GUID
的字符串表示形式,则可以跳过设置器。
答案 1 :(得分:1)
在大多数情况下,我使用公共财产,因为通常需要在那里完成所有工作。但也有例外(例如,如果验证需要进行一次)。所以你一般都说不出来。
答案 2 :(得分:1)
我建议使用公共设置器而不是变量的本地设置,因为只有一个地方 - 设置器 - 处理与验证相关的所有逻辑。但是,只有在类中的每个位置和所有派生版本严格遵循此约定时,这才有效。
我们不能假设成员变量不会在类中的其他地方(或者它的派生版本,如果它受到保护)被操纵。想象一下,另一个程序员调试与用户名验证相关的错误。在搜索时发现所有验证都是通过setter进行的,这是一个令人愉快的惊喜 - 所以她没有调试多个验证逻辑。
答案 3 :(得分:1)
在类中使用公共访问器是可以的,也可以使用任何公共方法。 (毕竟,属性只是getter / setter方法的语法糖。)
如果从类中访问属性与从外部访问属性具有相同的语义,则在内部使用访问器可能是首选。
此外,访问器为处理常规和自动实现的属性提供了一致的方法。 (自动实现的只是不显式公开支持字段。)
此外,在构造函数之外,几乎可以肯定,访问器应该用于虚拟属性。
需要直接使用支持字段,而不是后门属性操作。
但是没有一般规则选择哪种方法。
答案 4 :(得分:0)
实际上你做得很好,自封装字段让你可以轻松地根据你的需要设置属性值:例如看看这个:
private readonly ProductManufacturer _productManufacturer = new ProductManufacturer();
private readonly IList<ProductCategory> _productCategories = new List<ProductCategory>();
public ProductManufacturer ProductManufacturer
{
get { return _productManufacturer; }
}
public IEnumerable<ProductCategory> ProductCategory
{
get { return _productCategories; }
}
现在您可以在其他地方获取产品类别列表的列表,或者您只能对产品类别执行其他操作,如下所示:
public void AddProductCategory(ProductCategory productCategory)
{
_productCategories.Add(productCategory);
}
有关自封装字段的更多信息,请查看:
http://www.refactoring.com/catalog/selfEncapsulateField.html