我应该使用set once变量吗?

时间:2009-07-03 13:10:35

标签: c#

这闻到了吗?
我有一些你只能设置一次的属性。它们可以在物体存在期间的任何时间设置,并且不能撤消 我就是这样实现的。

    private FooThingy _foo;
    public FooThingy Foo
    {
        set { if (null == _foo) _foo = value; }
        get { return _foo; }
    }

但我不喜欢它。我觉得我错过了什么。我有吗?

编辑:为什么我在构造函数中没有它。 我无法详细说明,但设置此结果为 <坏的类比> 将蜡像熔化 < /坏类比{ {1}} 即可。而且我不希望我的构造函数创建已经融化的对象。

8 个答案:

答案 0 :(得分:19)

Set-once-properties违反最小意外原则 - 调用者希望当属性设置一次时,可以再次设置它。 (当然,除了范围和兼容性检查 - 但它们与特定值或值组合绑定)。

在构造函数中初始化它们 或者,如果要编写所有构造函数的许多/复杂,请使用工厂/构建器类:

ThingieBuilder tb = new ThingieBuilder();
tb.FooThingy = 17.23;   // r/w properties
tb.BarThingy = 42;
tb.UseExtendedThingamagicAdapter = true;
Thingie t = tb.Create();
if (t.Bar==42) // r/o property
  ...

或者,将配置对象中的设置分开,可以在构造期间替换或传递。

答案 1 :(得分:12)

我认为如果将这些值传递给构造函数,并且将其作为只读属性公开,则调用者的设计会更清晰。如果在构造时不能设置该值,那么在尝试再次设置该值时可能适合抛出异常:

private FooThingy _foo;
public FooThingy Foo
{
    set 
    { 
        if (null == _foo) { _foo = value; }
        else  { throw new WhatEverThatFitsException(); }
    }
    get { return _foo; }
}

非常清楚:我不 促进使用set-once属性;代码示例仅显示我可能使用的方法,如果该值在对象的构造时间不可用,无论出于何种原因。那说;在我参与的任何项目中,我从未遇到过这种情况。

答案 2 :(得分:4)

我建议在构造时设置它们,从而使setter私有化。这似乎是一种更明智的方式。

如果您打算这样做,请抛出某种异常。至少让开发人员知道你没有设置他们的价值而不是默默地忽略它。

答案 3 :(得分:1)

我同意弗雷德里克的看法,只会更有意义。这样,您只能在构造函数中声明您的变量(或作为声明的一部分)。我认为做你正在做的事情并不能立即明白这就是你想要实现的目标。

查看this MSDN页面。

答案 4 :(得分:1)

只需设置setter方法而不是属性 - 并且期望和行为之间的脱节就会消失。该方法可以自由地抛出InvalidOperationException - 但是让属性设置器执行它是意料之外的。

private FooThingy _foo;
public FooThingy Foo
{
    get { return _foo; }
}

public void SetFooThingy(FooThingy value) {
   if (Foo != null) 
      throw new InvalidOperationException("Foo is already set!");
   _foo = value;
}

答案 5 :(得分:0)

如果FooThingy是一个像int这样的值对象,它将被初始化为0而不是null。其余的看起来没问题

答案 6 :(得分:0)

从这个玩具示例中很难说,但听起来_foo对于这个对象的存在来说相对重要。在这种情况下,它几乎肯定应该是一个只在创建时初始化的readonly属性,而不是任何公共setter。尽可能地支持不可变对象;它让你的生活更加简单!

答案 7 :(得分:0)

使它们readonly并在构造函数中设置它们。