16

我同意 Mark Seeman 的观点,即自动属性在破坏封装时有些邪恶。不过,我确实喜欢它们带来的简洁语法、可读性和便利性。

我引用:

public string Name { get; set; }

代码片段的问题不在于它包含太多仪式。问题是它破坏了封装。实际上

“[...] getter 和 setter 没有实现封装或信息隐藏:它们是一种语言合法化的违反它们的方式。”</p>

James O. Coplien & Gertrud Bjørnvig。精益架构。威利。2010 年。134.

大多数情况下,添加非空保护子句对于属性设置器来说已经足够了,我想知道是否有比以下方法更好的方法。更好,我的意思是更简洁/更少重复的方式。

使用代码契约:

private string _username;
public virtual string Username
{
    get { return _username; }
    set 
    {  
        Contract.Requires(value != null);
        _username = value; 
    }
}

使用香草 .NET:

private string _username;
public virtual string Username
{
    get { return _username; }
    set 
    {
        if (value == null) throw new ArgumentNullException("Username");
        _username = value; 
    }
}
4

3 回答 3

7

我将仅引用代码合同手册第 2.3.1 节:

public int MyProperty { get; private set ; }

[ContractInvariantMethod]
private void ObjectInvariant () 
{
      Contract. Invariant ( this.MyProperty >= 0 );
      ...
}
于 2011-07-21T21:29:21.130 回答
0

我会假设属性只是从用户的角度来看的内存缓冲区。仅当在用户代码中调用方法(操作)时,才应检查属性缓冲区的有效性(例如,空检查会引发异常)。

如果分配的数据无效(在您的算法设计中),您的属性设置器应该向内部成员放置一个无效值。错误检查和返回应该来自使用这个属性值的方法

于 2011-07-21T08:33:00.297 回答