Should I use set variables?

Does this smell?
I have several properties that you can set only once. They can be installed at any time during the existence of objects and cannot be canceled.
Then I will realize it.

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

But I do not like it. I feel like I missed something. I have?

Change Why I do not have this in the constructor.
I cannot go into details, but setting this result to < bad analogy > . Melting Wax Statue < / bad analogy > . And I do not want my constructor to create already molten objects.

+4
c #
source share
8 answers

Complex properties violate the principle of least surprise - the caller expects that when the property can be set once, it can be set again. (of course, spaces and compatibility checks, but they are tied to specific values โ€‹โ€‹or combinations of values).

Initialize them in the constructor.
Alternatively, if they are for many / difficult to write all the constructors, use the factory / builder class:

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

Or separate the settings in the configuration object, which can be replaced or transferred at build time.

+18
source share

I think the design will be more understandable to the caller if such values โ€‹โ€‹are passed to the constructor and displayed as read-only properties. If the value cannot be set at build time, it might be advisable to throw an exception if you try to set the value again:

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

Just to be extremely clear: I in no way support the use of set-once properties ; the sample code shows only the approach that I could use if the value would not be available during the construction of the object for any reason. That said; I have never encountered this situation in any of the projects in which I participated.

+12
source share

I suggest installing them during construction and, therefore, making setters private. This seems like a more reasonable way.

If you are going to do this, throw some kind of exception. At least let the developer know that you did not set your values, but did not ignore it silently.

+4
source share

I agree with Fredrik, readonly will make more sense. This way you can only declare your variable in the constructor (or as part of the declaration). I think that to do what you do does not immediately become clear that this is what you want to achieve.

Check this MSDN page.

+1
source share

Just create utility methods, not properties - and the disconnection between expectations and behavior will disappear. This method can freely raise an InvalidOperationException, but this is unexpected if it has the setter property.

 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; } 
+1
source share

if FooThingy is a value object such as int, it will be initialized instead of zero. For the rest it looks ok

0
source share

It's hard to say from this toy example, but it seems that _foo relatively important for the existence of this object. In this case, it will almost certainly be the readonly property, which is initialized at creation time and has no public setter. Use immutable objects whenever possible; it makes your life a lot easier!

0
source share

Make them readonly and set them in the constructor.

0
source share

All Articles