Quando si progetta una classe, la coerenza nel comportamento dovrebbe essere favorita rispetto alla pratica di programmazione comune? Per fare un esempio specifico:
Una convenzione comune è questa: se una classe possiede un oggetto (ad es. Lo ha creato) è responsabile di ripulirlo una volta fatto. Un esempio specifico potrebbe essere in .NET che se la tua classe possiede un IDisposable
oggetto, dovrebbe eliminarlo alla fine della sua vita. E se non lo possiedi, non toccarlo.
Ora, se osserviamo la StreamWriter
classe in .NET, possiamo trovare nella documentazione che chiude il flusso sottostante quando viene chiuso / eliminato. Ciò è necessario nei casi in cui StreamWriter
viene istanziato passando un nome file mentre il writer crea il flusso di file sottostante e quindi deve chiuderlo. Tuttavia si può anche passare in un flusso esterno che anche lo scrittore chiude.
Questo mi ha infastidito un sacco di volte (sì, lo so che puoi creare un wrapper senza chiusura, ma non è questo il punto), ma a quanto pare Microsoft ha preso la decisione che è più coerente chiudere sempre il flusso, non importa da dove provenga.
Quando mi imbatto in un tale schema in una delle mie classi di solito creo una ownsFooBar
bandiera che viene impostata su false nei casi in cui FooBar
viene iniettata tramite il costruttore e su true in caso contrario. In questo modo la responsabilità di ripulirla viene trasferita al chiamante quando passa esplicitamente l'istanza.
Ora mi chiedo se forse la coerenza dovrebbe essere a favore delle migliori pratiche (o forse la mia migliore pratica non è così buona)? Qualche argomento a favore / contro di esso?
Modifica per chiarimenti
Con "coerenza" intendo: il comportamento coerente della classe che assume sempre la proprietà (e chiude il flusso) vs "best practice" per diventare proprietario di un oggetto solo se lo hai creato o trasferito esplicitamente la proprietà.
Come per un esempio in cui sta provando:
Supponiamo di avere due classi date (da una libreria di terze parti) che accettano uno stream per fare qualcosa con esso, come la creazione e l'elaborazione di alcuni dati:
public class DataProcessor
{
public Result ProcessData(Stream input)
{
using (var reader = new StreamReader(input))
{
...
}
}
}
public class DataSource
{
public void GetData(Stream output)
{
using (var writer = new StreamWriter(output))
{
....
}
}
}
Ora voglio usarlo in questo modo:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Ciò fallirà con un'eccezione Cannot access a closed stream
nel processore dei dati. È un po 'costruito ma dovrebbe illustrare il punto. Esistono vari modi per risolverlo, ma comunque sento di aggirare qualcosa che non dovrei dover fare.