Ich muss oft eine Klasse implementieren, die eine Aufzählung / Sammlung von etwas ist. Betrachten wir für diesen Thread das erfundene Beispiel von IniFileContent
denen ist eine Aufzählung / Sammlung von Linien.
Der Grund, warum diese Klasse in meiner Codebasis vorhanden sein muss, ist, dass ich vermeiden möchte, dass Geschäftslogik über den gesamten Ort verteilt wird (= Kapselung der where
), und dies auf möglichst objektorientierte Weise.
Normalerweise würde ich es wie folgt implementieren:
public sealed class IniFileContent : IEnumerable<string>
{
private readonly string _filepath;
public IniFileContent(string filepath) => _filepath = filepath;
public IEnumerator<string> GetEnumerator()
{
return File.ReadLines(_filepath)
.Where(l => !l.StartsWith(";"))
.GetEnumerator();
}
public IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Ich entscheide mich für die Implementierung, IEnumerable<string>
weil es die Verwendung bequemer macht:
foreach(var line in new IniFileContent(...))
{
//...
}
Allerdings frage ich mich, ob dies die Klassenabsicht "beschattet"? Wenn man sich IniFileContent
die Oberfläche ansieht , sieht man nur Enumerator<string> GetEnumerator()
. Ich denke, es ist nicht offensichtlich, welchen Service die Klasse tatsächlich anbietet.
Betrachten Sie dann diese zweite Implementierung:
public sealed class IniFileContent2
{
private readonly string _filepath;
public IniFileContent2(string filepath) => _filepath = filepath;
public IEnumerable<string> Lines()
{
return File.ReadLines(_filepath)
.Where(l => !l.StartsWith(";"));
}
}
Was weniger bequem verwendet wird (übrigens new X().Y()
fühlt sich das Sehen so an, als ob beim Klassendesign etwas schief gelaufen ist):
foreach(var line in new IniFileContent2(...).Lines())
{
//...
}
Aber mit einer klaren Oberfläche IEnumerable<string> Lines()
, die deutlich macht, was diese Klasse tatsächlich kann.
Welche Implementierung würden Sie fördern und warum? Ist es implizit eine gute Praxis, IEnumerable zu implementieren, um eine Aufzählung von etwas darzustellen?
Ich suche keine Antworten darauf, wie man:
- Unit-Test diesen Code
- Machen Sie eine statische Funktion anstelle einer Klasse
- Machen Sie diesen Code anfälliger für zukünftige Entwicklungen der Geschäftslogik
- Leistung optimieren
Blinddarm
Hier ist die Art von echtem Code , der in meiner Codebasis lebt und implementiert wirdIEnumerable
public class DueInvoices : IEnumerable<DueInvoice>
{
private readonly IEnumerable<InvoiceDto> _invoices;
private readonly IEnumerable<ReminderLevel> _reminderLevels;
public DueInvoices(IEnumerable<InvoiceDto> invoices, IEnumerable<ReminderLevel> reminderLevels)
{
_invoices = invoices;
_reminderLevels = reminderLevels;
}
public IEnumerator<DueInvoice> GetEnumerator() => _invoices.Where(invoice => invoice.DueDate < DateTime.Today && !invoice.Paid)
.Select(invoice => new DueInvoice(invoice, _reminderLevels))
.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
new
für diesen Anwendungsfall, Schwierigkeiten beim Testen von Einheiten, mehrdeutig, wenn ich / O Ausnahmen können auftreten usw. Es tut mir leid, ich versuche nicht unhöflich zu sein. Ich glaube, ich habe mich zu sehr an die Vorteile der Abhängigkeitsinjektion gewöhnt .
IniFileContent
.