Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use set once variables?

Tags:

c#

Does this smell?
I have a few properties you can only set once. They can be set at any time during the objects existence and can not be undone.
I implement then like this.

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

But I don't like it. I feel like I have missed something. Have I?

Edit: Why I don't have it in the constructor.
I cant go into the details but setting this results in <bad analogy> Melting the wax statue </bad analogy>. And I don't want my constructor to create already melted objects.

like image 278
Nifle Avatar asked Nov 27 '22 02:11

Nifle


2 Answers

Set-once-properties violate the principle of least surprise - a caller expects that when a property can be set once, it can be set again. (barring range and compatibility checks, of course - but they are bound to specific values or value combinations).

Initialize them in the constructor.
Alternatively, if they are to many / to complex to write all constructors, use a 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 a configuration object, that can be replaced or passed during construction.

like image 190
peterchen Avatar answered Dec 28 '22 08:12

peterchen


I think the design would be more clear to the caller if such values are passed to the constructor, and exposed as read-only properties instead. If the value can't be set at construction time, perhaps it could be appropriate to throw an exception if trying 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 very clear: I do not in any way promote the use of set-once properties; the code sample only show the approach that I might use, should the value not be available at construction time of the object for whatever reason. That said; I have never come across that situation in any of the projects I have been involved in.

like image 38
Fredrik Mörk Avatar answered Dec 28 '22 08:12

Fredrik Mörk