我应该使用set once变量吗?

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

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

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

编辑 :为什么我在构造函数中没有它。
我不能进入细节,但设置这个结果<坏类比>熔化蜡像< /坏比喻> 。 而且我不希望我的构造函数创建已经融化的对象。

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 ... 

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

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

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

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

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

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

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

查看此 MSDN页面。

只需制作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; } 

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

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

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