Frage

    

Diese Frage bereits eine Antwort hier:

         

Ich habe Methoden Privatsammlungen an den Aufrufer zurückkehrt, und ich möchte den Anrufer verhindern, dass die zurückgegebenen Sammlungen zu ändern.

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, um den Anrufer aus Modifizieren der Sammlung zu verhindern. Wiederkehrende IEnumerable<T> ist die einfachste Lösung, aber der Anrufer kann noch bis Guss des Rückgabewertes IList<T> und die Sammlung zu ä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.

  1. Wrapping die Sammlung in ReadOnlyCollection<T>.
  2. Zurückgeben einer der LINQ Iteratoren durch die Enumerable Klasse definiert durch einen Dummy-Vorsprung wie list.Select(item => item) durchführt. Eigentlich prüfen, mit mir Where(item => true), weil der zurückgegebene Iterator leichter scheint.
  3. Schreiben Sie eine benutzerdefinierte Wrapper.

Was ich mag nicht über ReadOnlyCollection<T> ist, dass es implementiert IList<T> und ruft Add() oder den Indexer zugreifen, werden Ausnahmen verursachen. Während diese absolut richtig in der Theorie ist, so gut wie kein echter Code prüft IList<T>.IsReadOnly oder IList<T>.IsFixedSize.

Mit der LINQ Iteratoren - ich den Code in einer Erweiterungsmethode MakeReadOnly() gewickelt - verhindert dieses Szenario, aber es hat den Geschmack eines Hack

.

Das Schreiben eines benutzerdefinierten Wrapper? Das Rad neu erfinden?

Alle Gedanken, Überlegungen oder andere Lösungen?


Während diese Frage Tagging, entdeckte ich diese Frage Stack-Überlauf ich habe nicht vor bemerken. Jon Skeet vorschlägt den "LINQ Hack" zu verwenden, auch, aber noch effizienter mit Skip(0).

War es hilfreich?

Lösung

Leider gibt es keine Möglichkeit, zu erreichen genau , was Sie suchen in der aktuellen Version des Frameworks. Es hat einfach kein Konzept einer Wende unveränderlich / schreibgeschützte Sammlung sowohl von der konkreten Art und Interface Design.

Wie Sie wies darauf hin, ReadOnlyCollection<T> funktioniert OK auf dem Beton Typ-Seite. Aber es gibt keine entsprechende Schnittstelle zu implementieren, die auch statisch schreibgeschützt ist.

Sie sind nur echte Wahl ist ...

  • Definieren Sie Ihre eigene Sammlung Klasse
  • Entweder nur IEnumerable<T> implementieren oder eine Notwendigkeit schreibgeschützte Schnittstelle, die Ihre Sammlung Geräte definieren.

Andere Tipps

Wie wäre es eine tiefe Kopie des Objekts machen zurückgegeben werden? [So wird es keine Auswirkungen auf die ursprüngliche Sammlung sein, auch wenn der Anrufer Änderungen an der Kopie zu machen entscheidet zurück]

Liste und Array haben eine AsReadOnly Methode:

public IEnumerable<Foo> GetFoos()
{
    return Array.AsReadOnly(this.foos);
    // or if it is a List<T>
    // return this.foos.AsReadOnly();
}

In diesem Fall erstelle ich ein Verfahren insde die Klasse einzelne Elemente der Privatsammlung zuzugreifen. Sie können auch erkennen, Indexer ( http://msdn.microsoft.com/en- us / library / 6x16t2tx.aspx ) auf der Klasse, die Privatsammlung enthält.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top