Die Antworten auf Fragen wie diese: List <T> oder IList <T> scheinen immer zuzustimmen, dass die Rückgabe einer Schnittstelle besser ist als die Rückgabe einer konkreten Implementierung einer Sammlung. Aber ich kämpfe damit. Das Instanziieren einer Schnittstelle ist nicht möglich. Wenn Ihre Methode also eine Schnittstelle zurückgibt, gibt sie tatsächlich immer noch eine bestimmte Implementierung zurück. Ich habe ein bisschen damit experimentiert, indem ich 2 kleine Methoden geschrieben habe:
public static IList<int> ExposeArrayIList()
{
return new[] { 1, 2, 3 };
}
public static IList<int> ExposeListIList()
{
return new List<int> { 1, 2, 3 };
}
Und benutze sie in meinem Testprogramm:
static void Main(string[] args)
{
IList<int> arrayIList = ExposeArrayIList();
IList<int> listIList = ExposeListIList();
//Will give a runtime error
arrayIList.Add(10);
//Runs perfectly
listIList.Add(10);
}
In beiden Fällen, wenn ich versuche, einen neuen Wert hinzuzufügen, gibt mir mein Compiler keine Fehler, aber offensichtlich gibt die Methode, die mein Array als darstellt, IList<T>
einen Laufzeitfehler aus, wenn ich versuche, etwas hinzuzufügen. So können die Leute , die nicht wissen , was in meiner Methode geschieht, und Werte , um es hinzuzufügen müssen, zu gezwungen sind , kopieren Sie zuerst meine IList
auf eine List
Lage sein , Werte hinzuzufügen , ohne Fehler zu riskieren. Natürlich können sie einen Typcheck durchführen, um festzustellen, ob es sich um ein List
oder ein handelt Array
, aber wenn sie dies nicht tun und der Sammlung Elemente hinzufügen möchten, haben sie keine andere Wahl, um das IList
in ein zu kopieren List
, selbst wenn es ist schon einList
. Sollte ein Array niemals als belichtet werden IList
?
Ein weiteres Anliegen von mir basiert auf der akzeptierten Antwort auf die verknüpfte Frage (Schwerpunkt Mine):
Wenn Sie Ihre Klasse über eine Bibliothek verfügbar machen, die andere verwenden, möchten Sie sie im Allgemeinen über Schnittstellen und nicht über konkrete Implementierungen verfügbar machen. Dies ist hilfreich, wenn Sie die Implementierung Ihrer Klasse später ändern, um eine andere konkrete Klasse zu verwenden. In diesem Fall müssen die Benutzer Ihrer Bibliothek ihren Code nicht aktualisieren, da sich die Benutzeroberfläche nicht ändert.
Wenn Sie es nur intern verwenden, ist es Ihnen vielleicht nicht so wichtig, und die Verwendung von List ist möglicherweise in Ordnung.
Stellen Sie sich vor, jemand hat meine IList<T>
von meiner ExposeListIlist()
Methode erhaltenen einfach so verwendet, um Werte hinzuzufügen / zu entfernen. Alles funktioniert gut. Aber jetzt, wie die Antwort andeutet, gebe ich ein Array anstelle einer Liste zurück (kein Problem auf meiner Seite!), Da die Rückgabe einer Schnittstelle flexibler ist.
TLDR:
1) Das Freilegen einer Schnittstelle verursacht unnötige Besetzungen? Ist das nicht wichtig?
2) Manchmal, wenn Benutzer der Bibliothek keine Besetzung verwenden, kann ihr Code beim Ändern Ihrer Methode beschädigt werden, obwohl die Methode vollkommen in Ordnung bleibt.
Ich überdenke das wahrscheinlich, aber ich bin mir nicht einig, dass die Rückgabe einer Schnittstelle der Rückgabe einer Implementierung vorzuziehen ist.
IEnumerable<T>
Sie zurück und Sie haben Kompilierungszeitsicherheit. Sie können weiterhin alle LINQ-Erweiterungsmethoden verwenden, die normalerweise versuchen, die Leistung zu optimieren, indem Sie sie in einen bestimmten Typ umwandeln (SieICollection<T>
möchten dieCount
Eigenschaft verwenden, anstatt sie aufzuzählen).