Modello di oggetto immutabile in C#:cosa ne pensi?

Modello di oggetto immutabile in C#:cosa ne pensi?

Per info, il secondo approccio si chiama "immutabilità del ghiacciolo".

Eric Lippert ha una serie di post sul blog sull'immutabilità che iniziano qui. Sto ancora facendo i conti con il CTP (C# 4.0), ma sembra interessante cosa potrebbero fare i parametri opzionali/denominati (per .ctor) (quando mappati su campi di sola lettura)...[aggiornamento:ho bloggato su questo qui]

Per info, probabilmente non farei quei metodi virtual - probabilmente non vogliamo che le sottoclassi siano in grado di renderlo non congelabile. Se vuoi che siano in grado di aggiungere codice extra, ti suggerirei qualcosa come:

[public|protected] void Freeze()
{
    if(!frozen)
    {
        frozen = true;
        OnFrozen();
    }
}
protected virtual void OnFrozen() {} // subclass can add code here.

Inoltre - AOP (come PostSharp) potrebbe essere un'opzione praticabile per aggiungere tutti quei controlli ThrowIfFrozen().

(mi scuso se ho cambiato la terminologia/i nomi dei metodi - SO non mantiene visibile il post originale durante la composizione delle risposte)


Un'altra opzione sarebbe quella di creare una sorta di classe Builder.

Ad esempio, in Java (e C# e molti altri linguaggi) String è immutabile. Se vuoi fare più operazioni per creare una stringa, usi uno StringBuilder. Questo è mutabile, e quindi una volta che hai finito, ti viene restituito l'oggetto String finale. Da quel momento in poi è immutabile.

Potresti fare qualcosa di simile per le altre classi. Hai il tuo elemento immutabile e poi un ElementBuilder. Tutto ciò che il builder farebbe è memorizzare le opzioni che hai impostato, quindi quando lo finalizzi costruisce e restituisce l'Elemento immutabile.

È un po' più di codice, ma penso che sia più pulito che avere setter su una classe che dovrebbe essere immutabile.


Dopo il mio iniziale disagio per il fatto che dovevo creare un nuovo System.Drawing.Point su ogni modifica, ho abbracciato completamente il concetto alcuni anni fa. In effetti, ora creo ogni campo come readonly per impostazione predefinita e cambialo in modo che sia mutevole solo se c'è un motivo convincente, cosa sorprendentemente rara.

Tuttavia, non mi interessa molto dei problemi di cross-threading (uso raramente il codice dove è rilevante). Lo trovo molto, molto meglio grazie all'espressività semantica. L'immutabilità è l'epitome stesso di un'interfaccia che è difficile da usare in modo errato.