2014-01-30 37 views
1

所以我有一个简单的类,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

这是可以的,你使用自封装字段 – Grundy

+0

我认为accessor的主要工作是只有。否则,我们可以使用公共变量。只是为了验证我们有属性的输入。 –

+0

请参阅http://blogs.msdn.com/b/ericlippert/archive/2009/01/14/automatic-vs-explicit-properties.aspx –

回答

1

我建议在变量的本地设置中使用公共setter,只是因为会有一个地方 - setter - 所有与验证有关的逻辑都被处理。但是这只有在你严格按照这个惯例在类和所有衍生版本中的每一个地方进行时才有效。

人们不能假定成员变量在类中的其他地方(或其派生版本,如果它受保护的话)没有被操纵。想象另一位程序员调试与用户名验证相关的错误。在搜索时发现所有的验证都是通过setter进行的 - 所以她不必调试多个验证逻辑,这可能是一个令人愉快的惊喜。

+0

这就是我所想的,知道数据在开始时处于正确的形式,也可以减少对班级中某些错误处理的需求。 – mbdavis

1

答案取决于数据来自何处。由于支持使用二传手的驱动点是为了避免重复验证代码,你有两种基本情况:

  • 当数据从你的类外部的(即通过方法的参数,因为在你的例子),那么你应该调用setter,它会为你执行验证。
  • 当数据在您准备分配的位置已经“消毒”后,直接转到变量,绕过验证。

前一种情况延伸到读取用户输入的情况。

后面的情况包括从快照恢复对象状态或在内部生成对象状态的情况。例如,如果您的setter具有null /空字符串验证,并且您的方法想要将字符串设置为GUID的字符串表示形式,则可以跳过setter。

+0

在类访问器中抛出未经过清理的数据是好的还是不好的做法?或者我应该先清理一下,然后让班级直接分配。我唯一遇到的问题是,如果这个类被重用,它可以在没有消毒输入的情况下使用,这意味着要处理错误,我不得不在其他类方法中添加更多的错误处理。 – mbdavis

+1

@mbdavis所有直接分配应该发生在私有方法内部。应该没有人重用类来通过“已清理”数据路径推送他的数据的路径 - 例如,应该没有受保护的方法来分配值而不先检查它,以防止您描述的情况(即由于不正确地重用班级而导致的错误)。 – dasblinkenlight

+0

好的,我会坚持使用accessors。谢谢你的帮助! – mbdavis

1

在大多数情况下,我使用公共属性,因为通常需要做的事情都需要随时完成。但也有例外情况(例如,如果验证需要进行一次)。所以你不能一般地说出来。

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

1

在一个班级内使用公共访问器是可以的,以及使用任何公共方法。 (毕竟,属性只是getter/setter方法的语法糖。)

在内部使用访问器可能更适用于从类中访问属性具有与从外部访问属性相同的语义。

此外,访问器提供了一致的方式来处理常规和自动实现的属性。 (自动实现的只是不显式支持域)

此外,在构造函数之外,几乎可以肯定,访问器应该用于虚拟属性。

直接使用背景场​​是需要的,而不是后门属性操作。

但是没有一般的规则选择哪种方法。

+0

谢谢,很好地解释说,我喜欢你的比较,可以称之为公共方法。 – mbdavis

相关问题