So, we all understand the benefits of immutable types, especially in multi-threaded scenarios. (Or at least we all need to understand this; see, for example, System.String.)
However, I have not seen much discussion for creating immutable instances, in particular for developing recommendations.
For example, suppose we want to have the following immutable class:
class ParagraphStyle {
public TextAlignment Alignment {get;}
public float FirstLineHeadIndent {get;}
}
The most common approach I've seen is to have mutable / immutable "pairs" of types, for example. a modified List <T> and immutable ReadOnlyCollection <T> types or mutable StringBuilder and immutable String types.
To mimic this existing pattern, you will need to introduce some type of "mutable" type ParagraphStyle, which "duplicates" the members (to provide setters), and then provides a constructor ParagraphStylethat takes a mutable type as an argument
class ParagraphStyleCreator {
public TextAlignment {get; set;}
public float FirstLineIndent {get; set;}
}
class ParagraphStyle {
public ParagraphStyle (ParagraphStyleCreator value) {...}
}
var paragraphStyle = new ParagraphStyle (new ParagraphStyleCreator {
TextAlignment = ...,
FirstLineIndent = ...,
});
So it works, supports code completion in the IDE, and makes things reasonably obvious on how to build things ... but it seems pretty duplicate.
Is there a better way?
For example, anonymous C # types are immutable, and allow the use of initialization for "normal" properties:
var anonymousTypeInstance = new {
Foo = "string",
Bar = 42;
};
anonymousTypeInstance.Foo = "another-value";
Unfortunately, the closest way to duplicate this semantics in C # is to use constructor options:
class ParagraphStyle {
public ParagraphStyle (TextAlignment alignment, float firstLineHeadIndent,
) {...}
}
" "; , , 15 , 15 , , "" 15 - . .
, , "set-once" "" , , "" :
class ParagraphStyle {
bool alignmentSet;
TextAlignment alignment;
public TextAlignment Alignment {
get {return alignment;}
set {
if (alignmentSet) throw new InvalidOperationException ();
alignment = value;
alignmentSet = true;
}
}
}
, , (, , ), . , Commit(), , ( , , , ), , .
, / ? ?