0

I have a DataStructure class, which I want to be immutable.

Ordinarily, I'd just ensure that all my members are defined as readonly - Job Done. But one of the members is a list (of ints), so I need to ensure that the List can't be modified; so I change it to a ReadOnlyCollection<T>. Fine.

I also need that collection to be ordered in a certain way - again fine, I sort the list accordingly before converting it via .AsReadOnly().

So far, it's all been fine.

But the last step is that I want 3 different constructors - each accepting the original data in a different format. Now I have to duplicate the code that converts the list to the necessary format, in each constructor.

If I commonise it out into a setList() method, then the variable can't be readonly, because it's being assigned in a non-constructor method. Now I've lost some of the immutability.

Ideally, there would be some way that I can declare that the setList method can only be called from a constructor, and thus is allowed to edit readonly members, but I don't think that exists.

I could create wrap everything in getters and so forth, so that the class is immutable from the outside, but I'd rather like it to be immutable from the inside too (especially given that I can achieve this is I sacrifice DRYness)

Does anyone have any clever ideas about language features I've forgotten about that would solve this?

gturri
  • 13,807
  • 9
  • 40
  • 57
Brondahl
  • 7,402
  • 5
  • 45
  • 74

2 Answers2

2

Rather than using a void SetList(List) called from constructors, you could have a List PrepareList(List). This method would prepare the list, and return it to the callers -ie: the constructors.

So the code wouldn't be repeated -except an affectation _list = PrepareList(list) in each constructors.

gturri
  • 13,807
  • 9
  • 40
  • 57
0

You can keep it as a normal list inside your class, but only expose it as readonly to the outside (just return .AsReadOnly() in a property).

Though if you definetely want the internal immutability, constructors can call each other:

public Foo( int a ) { ... }
public Foo( string a ) : this( int.Parse( a ) ) { ... }

So you can have most of the code in one constructor (even a private one if needed), and have the converting done in the others. Edit: it is a bit difficult to do alot of work that way, so I still think you should move the conversion out into methods. If the method doesn't access any class members, it'd still be internally immutable.

Another pattern I personally prefer (even if it's just syntactically different) is:

private Foo( int a ) { ... }

public static Foo FromBar( Bar b )
{
    int x;
    // convert from Bar here
    return new Foo( x );
}

public static Foo FromSomethingElse( SomeThingElse b )
{
    int x;
    // convert from SomeThingElse here
    return new Foo( x );
}
Chris
  • 5,442
  • 17
  • 30
  • Yes, I considerred the option of chaining the constructors together, but the body is way more complex than simply int.Parse() and the list isn't the only member I'm extracting from the inputs. I suppose I could define a bunch of methods that extract the vrious lists and other things, but that feels a bit ugly overall. Using static 'constructor' like methods, and then deferring to a true constructor to set the readonly members is a nice design. And failing any other solutions I would use that. – Brondahl Jul 06 '14 at 14:34
  • Then I'd say go with the static approach which will give you some more room to work! – Chris Jul 06 '14 at 14:36