这闻到了吗?
我有一些你只能设置一次的属性。它们可以在物体存在期间的任何时间设置,并且不能撤消
我就是这样实现的。
private FooThingy _foo;
public FooThingy Foo
{
set { if (null == _foo) _foo = value; }
get { return _foo; }
}
但我不喜欢它。我觉得我错过了什么。我有吗?
编辑:为什么我在构造函数中没有它。
我无法详细说明,但设置此结果为 <
坏的类比>
将蜡像熔化 <
/坏类比{ {1}} 即可。而且我不希望我的构造函数创建已经融化的对象。
答案 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并在构造函数中设置它们。