Ich habe Methoden, die private Auflistungen an den Aufrufer zurückgeben, und ich möchte verhindern, dass der Aufrufer die zurückgegebenen Auflistungen ändert.Wie kann verhindert werden, dass ein Methodenaufrufer eine zurückgegebene Sammlung ändert?
private readonly Foo[] foos;
public IEnumerable<Foo> GetFoos()
{
return this.foos;
}
Im Moment ist die Privatsammlung ist eine feste Anordnung, aber in der Zukunft die Sammlung könnte eine Liste werden, wenn die Notwendigkeit für das Hinzufügen neue Elemente zur Laufzeit entsteht.
Es gibt mehrere Lösungen, die verhindern, dass der Aufrufer die Sammlung ändert. Die Rückkehr IEnumerable<T>
ist die einfachste Lösung, aber der Aufrufer kann immer noch den Rückgabewert auf IList<T>
herauf-Cast und die Auflistung ändern.
((IList<Foo>)GetFoos())[0] = otherFoo;
die Sammlungen Klonen hat den offensichtlichen Nachteil, dass es zwei Sammlungen, die unabhängig voneinander entwickeln können. Bisher habe ich die folgenden Optionen in Betracht gezogen.
- Verpackung der Sammlung in
ReadOnlyCollection<T>
. - Zurückgeben eines der von der Klasse
Enumerable
definierten LINQ-Iteratoren durch Ausführen einer Dummy-Projektion wielist.Select(item => item)
. Eigentlich denke ich überWhere(item => true)
, weil der zurückgegebene Iterator leichter scheint. - Schreiben eines benutzerdefinierten Wrappers.
Was Ich mag nicht über ReadOnlyCollection<T>
ist, dass es implementiert IList<T>
und ruft Add()
oder den Zugriff auf die Indexer Ausnahmen verursachen. Während dies in der Theorie absolut korrekt ist, prüft fast kein echter Code IList<T>.IsReadOnly
oder IList<T>.IsFixedSize
.
Verwendung der LINQ-Iteratoren - Ich habe den Code in eine Erweiterungsmethode MakeReadOnly()
eingewickelt - verhindert dieses Szenario, aber es hat den Geschmack eines Hacks.
Schreiben eines benutzerdefinierten Wrappers? Das Rad neu erfinden?
Irgendwelche Gedanken, Überlegungen oder andere Lösungen?
Während diese Frage Tagging, entdeckte ich this Stack Overflow question ich vor nicht bemerkt. Jon Skeet schlägt vor, den "LINQ-Hack" auch zu verwenden, aber noch effizienter unter Verwendung von Skip(0)
.
Wenn es keine Sicherheitsprobleme (potentiell feindselige Anrufer) gibt, mache ich mir im Allgemeinen keine Gedanken über den Schutz vor unklugem Casting oder den Aufruf von Add in einer ReadOnlyCollection. Törichte Entwickler können Reflexionen verwenden und auch auf Interna zugreifen. Es ist schwierig, Code idiotensicher zu machen. Ziel ist es, vor unschuldiger Nutzung der öffentlichen Schnittstelle zu schützen. – TrueWill