Ciò che potresti voler ricordare è che i chiamanti possono presumere che il valore di una proprietà non cambia a meno che non sia stato assegnato esplicitamente. Questo non è necessariamente un presupposto intelligente, ma tuttavia è uno che sarà fatto.
Molti programmatori si aspettano il passaggio del seguente test:
var b1 = foo.Bounds;
var b2 = foo.Bounds;
Assert.AreEqual(b2, b1);
Ora, per qualcosa come un Rect
, questo probabilmente non è un grosso problema, specialmente se è immutabile (come sarebbe normalmente un Rect
) e un tipo di valore o ha un operatore di uguaglianza di valore. In questo caso, non importa se due chiamate diverse ottengono due istanze diverse perché è molto difficile scrivere codice che implicitamente dipende dal fatto che siano la stessa istanza.
Inoltre, lazy instantiation è quasi sempre soddisfacente:
public Rect Bounds
{
get
{
if (bounds == null)
bounds = GetBounds(...);
return bounds;
}
}
... perché le successive chiamate avranno la stessa istanza, escludendo eventuali problemi di multi-threading.
Ma le cose possono diventare difficili quando una proprietà effettivamente restituisce un'istanza diversa ogni volta, e quell'istanza è un oggetto abbastanza complesso e particolarmente mutevole.
Ad esempio, supponiamo che tu restituisca un Stream
:
public Stream OutputStream
{
get { return new FileStream(...); }
}
Questo è abbastanza orribile perché è molto probabile che qualcuno scriva codice come:
foo.OutputStream.Write(data1, 0, data1.Length);
foo.OutputStream.Write(data2, 0, data2.Length);
E a seconda di come hai implementato OutputStream
, accadrà una delle due cose brutte, o ci sarà un'eccezione di blocco file nella seconda chiamata, se OutputStream
fa sempre riferimento allo stesso file, o il chiamante potrebbe scrivere involontariamente dei dati su due file diversi (se, diciamo, OutputStream
crea effettivamente un nuovo file ogni volta), successivamente corrompendo entrambi i file.
Non aspettarti che i chiamanti salvino il valore di ritorno di una proprietà. Spesso non lo faranno. Quindi, se stai pensando di scrivere una proprietà che restituisce un oggetto diverso ogni volta, assicurati che non ci siano gravi rischi per far fluttuare due istanze nello stesso momento e possibilmente essere scambiate o perse.
Ho trascorso molte ore di debugging doloroso in cui sembrava che tutto funzionasse correttamente ma si è scoperto che stavo lavorando solo su una copia dell'istanza corretta. Gli iteratori con un'esecuzione differita sono un sottoinsieme particolarmente pernicioso di questo problema; non è insolito passare a foreach
una volta sola e modificare alcune proprietà di ogni elemento, quindi foreach
attraverso di essa e scoprire che tutto ha "reset"!
Un'ultima cosa: non si dovrebbe mai creare un oggetto che richiede la pulizia da un accessorio di proprietà. Non c'è quasi nessuna possibilità che il chiamante lo pulisca.