C# 在类中使用访问器是一种不好的做法吗?

C# 在类中使用访问器是一种不好的做法吗?,c#,class,field,encapsulation,accessor,C#,Class,Field,Encapsulation,Accessor,因此,我有一个简单的类,User,类似于这样(忽略可怕的空格使用,希望保持简短以便在线阅读): 在类中使用公共访问器来使用其验证是否更好?或者这是一种糟糕的做法,在这种情况下,我应该在设置私有用户名字段之前重新验证吗?答案取决于数据来自何处。由于使用setter背后的驱动点是避免重复验证代码,因此有两种基本情况: 当数据来自类外部(例如,通过方法参数,如示例中所示)时,您应该调用setter,它将为您执行验证 当数据在您准备分配的位置被“净化”后,直接转到变量,绕过验证 前一种情况扩展到读取

因此,我有一个简单的类,
User
,类似于这样(忽略可怕的空格使用,希望保持简短以便在线阅读):


在类中使用公共访问器来使用其验证是否更好?或者这是一种糟糕的做法,在这种情况下,我应该在设置私有
用户名
字段之前重新验证吗?

答案取决于数据来自何处。由于使用setter背后的驱动点是避免重复验证代码,因此有两种基本情况:

  • 当数据来自类外部(例如,通过方法参数,如示例中所示)时,您应该调用setter,它将为您执行验证
  • 当数据在您准备分配的位置被“净化”后,直接转到变量,绕过验证
前一种情况扩展到读取用户输入的情况


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

答案取决于数据来自何处。由于使用setter背后的驱动点是避免重复验证代码,因此有两种基本情况:

  • 当数据来自类外部(例如,通过方法参数,如示例中所示)时,您应该调用setter,它将为您执行验证
  • 当数据在您准备分配的位置被“净化”后,直接转到变量,绕过验证
前一种情况扩展到读取用户输入的情况


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

在大多数情况下,我使用public属性,因为通常需要始终在那里执行操作。但也有例外(例如,如果验证需要执行一次)。所以一般来说,你不能真的说不出来。

在大多数情况下,我使用公共财产,因为在那里做的事情通常需要一直做。但也有例外(例如,如果验证需要执行一次)。因此,一般来说,您不能真的说不出来。

我建议使用公共setter而不是变量的本地设置,因为只有一个地方——setter——处理与验证相关的所有逻辑。但是,只有在类中的每个地方以及所有派生版本都严格遵循此约定时,这才有效


不能假设成员变量未在类中的其他位置(或其派生版本,如果受保护的话)进行操作。设想另一个程序员调试与用户名验证相关的错误。在搜索时发现所有验证都是通过setter进行的,这可能是一个惊喜,这样她就不必调试多个验证逻辑。

我建议使用公共setter而不是变量的本地设置,因为只有一个地方——setter——处理与验证相关的所有逻辑。但是,只有在类中的每个地方以及所有派生版本都严格遵循此约定时,这才有效


不能假设成员变量未在类中的其他位置(或其派生版本,如果受保护的话)进行操作。设想另一个程序员调试与用户名验证相关的错误。在搜索时发现,所有验证都是通过setter进行的,这可能是一个惊喜,因此她不必调试多个验证逻辑。

事实上,您做得很好,自封装字段使您可以轻松地根据需要设置属性的值:例如,请看以下内容:

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; }
}
有关自封装字段的更多信息,请查看以下内容:

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; }
}

事实上,您做得很好,自封装字段使您可以轻松地根据需要设置属性值:例如,请看以下内容:

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; }
}
有关自封装字段的更多信息,请查看以下内容:

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; }
}

在类中使用公共访问器以及使用任何公共方法都可以。(毕竟,属性只是getter/setter方法的语法糖。)

如果从类内部访问属性与从外部访问属性具有相同的语义,则最好在内部使用访问器

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

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

直接使用支持字段,而不是后门属性操作


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

在类中使用公共访问器以及使用任何公共方法都是可以的。(毕竟,属性只是getter/setter方法的语法糖。)

如果从类内部访问属性与从外部访问属性具有相同的语义,则最好在内部使用访问器

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

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

直接使用支持字段