Sollte beim Entwerfen einer Klasse eine konsistente Verhaltensweise gegenüber der üblichen Programmierpraxis bevorzugt werden? Um ein konkretes Beispiel zu geben:
Eine übliche Konvention lautet: Wenn eine Klasse ein Objekt besitzt (z. B. es erstellt hat), ist sie dafür verantwortlich, es zu bereinigen, sobald es fertig ist. Ein spezielles Beispiel wäre in .NET, dass Ihre Klasse, wenn sie ein IDisposableObjekt besitzt, es am Ende seiner Lebensdauer entsorgen sollte. Und wenn Sie es nicht besitzen, berühren Sie es nicht.
Wenn wir uns nun die StreamWriterKlasse in .NET ansehen, können wir in der Dokumentation feststellen, dass sie den zugrunde liegenden Stream schließt, wenn er geschlossen / entsorgt wird. Dies ist in Fällen erforderlich, in denen StreamWriterdurch die Übergabe eines Dateinamens als Writer der zugrunde liegende Dateistream erstellt und daher geschlossen werden muss. Man kann aber auch einen externen Stream übergeben, den der Writer ebenfalls schließt.
Das hat mich viele Male geärgert (ja, ich weiß, dass Sie einen nicht schließenden Wrapper erstellen können, aber das ist nicht der Punkt), aber anscheinend hat Microsoft die Entscheidung getroffen, dass es konsistenter ist, den Stream immer zu schließen, egal woher er kommt.
Als ich kommen über ein solches Muster in einer meiner Klassen in der Regel ich schaffen ownsFooBarFlagge , die in den Fällen auf false gesetzt wird , wo FooBarüber den Konstruktor injiziert wird und ansonsten true. Auf diese Weise wird die Verantwortung für die Bereinigung auf den Aufrufer übertragen, wenn er die Instanz explizit übergibt.
Jetzt frage ich mich, ob vielleicht die Beständigkeit der Best Practice vorgezogen werden sollte (oder ob meine Best Practice nicht so gut ist). Irgendwelche Argumente dafür / dagegen?
Zur Verdeutlichung bearbeiten
Mit "Konsistenz" meine ich: Das konsistente Verhalten der Klasse, die immer den Besitz übernimmt (und den Stream schließt), im Gegensatz zu "Best Practice", den Besitz eines Objekts nur dann zu übernehmen, wenn Sie es erstellt oder den Besitz explizit übertragen haben.
Als Beispiel, wo es reizend ist:
Angenommen, Sie haben zwei Klassen (aus einer Bibliothek eines Drittanbieters), die einen Stream akzeptieren, um etwas damit zu tun, z. B. Daten zu erstellen und zu verarbeiten:
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))
{
....
}
}
}
Jetzt möchte ich es so benutzen:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Dies schlägt mit einer Ausnahme Cannot access a closed streamim Datenprozessor fehl . Es ist ein bisschen konstruiert, sollte aber den Punkt veranschaulichen. Es gibt verschiedene Möglichkeiten, das Problem zu beheben, aber ich habe trotzdem das Gefühl, dass ich etwas umgehe, das ich nicht müsste.