题 具有非null保护子句的自动实现的属性?


我同意马克·西曼的观点 自动属性有点邪恶 因为他们破坏了封装。但是,我确实喜欢它们带来的简洁语法,可读性和便利性。

我引用:

public string Name { get; set; }

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

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

James O. Coplien和GertrudBjørnvig。精益建筑。威利。 2010. p。 134。

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

使用代码合同:

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

使用vanilla .NET:

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

16
2017-07-21 08:23


起源


老实说,不要认为这是可能的。但是要好好倾听别人的意见。 - Tigran


答案:


我只想引用一下 代码合同 手册,§2.3.1:

public int MyProperty { get; private set ; }

[ContractInvariantMethod]
private void ObjectInvariant () 
{
      Contract. Invariant ( this.MyProperty >= 0 );
      ...
}

7
2017-07-21 21:29



这似乎是最接近我正在寻找的东西,即使它不是最佳的,因为它将在每个getter / setter上运行。 - Can Gencer
@Can:虽然有很多设置来控制它。 - Henk Holterman


您可以使用PostSharp中的方面来使用null检查来装饰属性setter:

http://www.sharpcrafters.com/blog/post/5-Ways-That-Postsharp-Can-SOLIDify-Your-Code-Lazy-Loading-of-Dependencies.aspx

如何在postsharp中为类中的所有方法创建方面检查空引用

http://magpie.sytes.net/jesperhogstrom/2010/11/compiler-safe-null-checking-of-arguments-with-aspects/


3
2017-07-21 08:29



我感觉PostSharp会出现。我想知道你对Castle Interceptors和自定义属性的性能有多大影响。 - Can Gencer


从用户的角度来看,我认为属性只是内存缓冲区。只有在用户代码中调用方法(动作)时,才应检查属性缓冲区的有效性(例如,空检查抛出异常)。

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


0
2017-07-21 08:33



我同意这一点,我倾向于在进入房产时进行验证 - 但是在使用该房产时进行验证。 - Adam Houldsworth
我明白你的观点,但我并不同意这一点,因为它违背了我所信奉的“快速失败”原则。 - Can Gencer
@Can我倾向于忽视那些不是UI的东西。特别是对于基于属性的类,比如使用Xaml的东西。财产有效性可能与另一财产的内容有关,该财产可能尚未设定。 - Adam Houldsworth
@Adam,我认为对于DTO来说这没关系,但对于域对象封装和状态验证非常重要。 - Can Gencer
@Can我没有说他们不是。没有在设置属性上进行验证不会破坏它,只要它稍后完成。 - Adam Houldsworth