Frage

Ich habe eine ICollection<T> foos in meiner Klasse genannt, die ich als schreibgeschützt verfügbar machen möchten (siehe diese Frage ). Ich sehe, dass die Schnittstelle eine Eigenschaft .IsReadOnly definiert, die ... angemessen scheint Meine Frage ist: Wie mache ich es für die Verbraucher der Klasse offensichtlich, dass foos schreibgeschützt ist?

Ich möchte ein nicht umgesetztes Verfahren vor dem Versuch, wie .IsReadOnly abfragen .Add() nicht auf sie verlassen zu erinnern. Im Idealfall würde Ich mag foos als ReadOnlyCollection<T> aussetzen, aber nicht IList<T> implementieren. Soll ich foo über eine Methode aufgerufen, beispielsweise GetReadOnlyFooCollection anstatt über eine Eigenschaft aussetzen? Wenn ja, würde verwechseln nicht jemand, der dann ein ReadOnlyCollection<T> erwartet?

Dies ist C # 2.0, so Erweiterungsmethoden wie ToList() nicht zur Verfügung steht ...

War es hilfreich?

Lösung

scheine ich bei der Rückkehr IEnumerable mit den geklonten Objekte niedergelassen zu haben.

public IEnumerable<Foose> GetFooseList() {
   foreach(var foos in Collection) {
     yield return foos.Clone();
   }
}
  • erfordert eine Clone-Methode auf Foos.

Auf diese Weise können keine Änderungen in der Sammlung. Denken Sie daran, dass Readonlycollection „leaky“ ist, da die Objekte im Innern verändert werden können, wie in einem Link in einem anderen Beitrag erwähnt.

Andere Tipps

Sie können "Foos" ein Readonlycollection wie folgt vor:

ReadOnlyCollection<T> readOnlyCollection = foos.ToList<T>().AsReadOnly();

Dann können Sie es als eine Eigenschaft Ihrer Klasse aus.

EDIT:

    class FooContainer
    {
        private ICollection<Foo> foos;
        public ReadOnlyCollection<Foo> ReadOnlyFoos { get { return foos.ToList<Foo>().AsReadOnly();} }

    }

Hinweis: Sie sollten bedenken, dass, sobald Sie die ReadOnlyFoos Sammlung bekommen, ist nicht mehr „synchronisiert“ mit Ihrem foos ICollection. Sehen Sie sich die Thread referenziert Sie .

Da die Frage geschrieben wurde, hat .NET 4.0 eine IReadOnlyCollection<T> Schnittstelle hinzugefügt; es wäre wahrscheinlich gut sein, dass als deklarierten Rückgabetyp zu verwenden.

Das hat jedoch lassen die Frage offen, welche Art von Instanz zurückzukehren. Ein Ansatz wäre es, alle Elemente in der ursprünglichen Sammlung zu klonen. Eine andere wäre, immer einen Nur-Lese-Wrapper zurück. Eine dritte wäre die ursprüngliche Sammlung zurück, wenn es IReadOnlyCollection<T> implementiert. Jeder Ansatz wird die beste in bestimmten Kontexten sein, wird aber weniger als ideal (oder vielleicht geradezu schrecklich) in anderen. Leider Microsoft bietet keine Standard Mittel, durch die eine Frage zwei sehr wichtige Fragen gestellt werden können:

  1. Sie versprechen Sie immer und für immer die gleichen Elemente enthalten, wie Sie jetzt tun?

  2. Können Sie sicher direkt an Code ausgesetzt werden, die angeblich nicht Ihre Inhalte zu ändern.

Welche Art von Verpackung ist angemessen, würde davon abhängen, was der Client-Code erwartet mit der Sache zu tun, die er empfängt. Einige Szenarien zu vermeiden:

  1. Ein Objekt wurde von einem Typ geliefert, dass der Client als unveränderlich erkennen würde, aber anstatt direkt zurückgegeben wird es dupliziert wird, eine Art verwendet, dass der Client nicht als unveränderlich nicht erkennt. Folglich wird der Kunde gezwungen, wieder um die Sammlung zu kopieren.

  2. Ein Objekt wurde von einem Typ geliefert, dass der Client als unveränderlich erkennen würde, aber bevor sie in einer solchen Art und Weise gewickelt wird zurückgegeben wird, dass der Client nicht sagen kann, ob die Sammlung unveränderlich ist oder nicht, und somit gezwungen, zu duplizieren.

  3. Ein Objekt von wandelbarem Typ, die angeblich nicht mutiert werden soll, wird von einem Client (Guss zu einer Read-Only-Schnittstelle) geliefert. Es wird dann direkt an einem anderen Kunden ausgesetzt, die feststellen, dass es ein veränderlicher Typ ist, und geht es zu ändern.

  4. Ein Verweis auf eine veränderbare Sammlung empfangen wird, und ist in einem Nur-Lese-Wrapper eingekapselt, bevor an einem Kunden zurückgegeben werden, die ein unveränderliches Objekt benötigt. Die Methode, die die Sammlung zurückgegeben versprochen, dass sie unveränderlich ist, und somit ging der Kunde seine eigene Verteidigungs Kopie. Der Kunde ist dann schlecht vorbereitet für die Möglichkeit, dass die Sammlung ändern könnte.

Es ist nicht wirklich besonders „sicher“ Vorgehensweise ein Objekt mit Sammlungen nehmen, die sie von einigen Kunden erhalten und muss andere belichten. Immer Duplizieren alles in vielen Fällen ist die sicherste Vorgehensweise, aber es kann in Situationen leicht führen, wo eine Sammlung, die nicht benötigen, sollte überhaupt endet immer dupliziert hunderte oder tausende Male dupliziert werden. Wiederkehrende Referenzen wie empfangen kann oft der effizienteste Ansatz sein, aber es kann auch semantisch gefährlich sein.

möchte ich Microsoft die Standardmittel hinzufügen würde, durch die Sammlungen die oben genannten Fragen oder noch besser gestellt werden könnten, aufgefordert werden, eine unveränderliche Momentaufnahme ihrer aktuellen Zustand zu erzeugen. Eine unveränderliche Sammlung sehr billig eine unveränderliche Momentaufnahme der aktuellen Zustand zurückkehren konnte (nur selbst zurück) und sogar einige wandelbar Sammlungstypen könnte eine unveränderliche Snapshot zu einem Preis weit unter den Kosten einer vollständigen Aufzählung zurückgeben (zB ein List<T> könnte durch zwei gesichert werden T[][] Arrays, von denen Verweise auf gemeinsam nutzbare unveränderliche Arrays von 256 Elementen enthält, und von denen die andere halten Verweise auf unsharable veränderbare Arrays von 256 Elementen. eine Momentaufnahme von einer Liste zu machen würde nur die innere Arrays enthält Elemente Klonieren erfordern, die modifiziert wurde, . seit dem letzten Snapshot - möglicherweise viel billiger als die ganze Liste Klonen Leider, da keine Standard-Schnittstelle gibt es „eine unveränderliche Schnappschuss machen“ [dass ICloneable beachten Sie zählt nicht, da ein Klon einer wandelbaren Liste wandelbar wäre, während ein machen eine könnteunveränderliche Snapshot durch einen wandelbaren Klon in einem Read-Only-Wrapper einkapseln, das wäre nur für die Dinge funktionieren, die klonbar sind, und sogar Arten, die nicht klonbar sind, sollten nach wie vor eine „veränderliches Snapshot“ -Funktion unterstützen.]

Meine Empfehlung ist direkt Gebrauch ein Readonlycollection für das Szenario zurückzukehren. Dies macht die Nutzung explizit an die anrufende Benutzer.

Normalerweise würde ich vorschlagen, die entsprechende Schnittstelle. Aber da das .NET Framework nicht zur Zeit eine geeignete IReadOnlyCollection hat, müssen Sie mit dem Readonlycollection Typ gehen.

Auch Sie müssen sich bewusst sein, wenn Readonlycollection verwenden, weil es eigentlich nicht schreibgeschützt ist: Unveränderlichkeit und Readonlycollection

Manchmal können Sie eine Schnittstelle verwenden, vielleicht, weil Sie die Sammlung während Unit-Tests verspotten wollen. Bitte beachten Sie meine Blog-Eintrag rel="nofollow für die eigene Schnittstelle zu Readonlycollection Zugabe unter Verwendung von ein Adapter.

ich in der Regel ein IEnumerable<T> zurück.

Wenn Sie eine Sammlung nur lesbar machen (so Methoden wie Add, Remove und Clear funktioniert nicht mehr) gibt es nicht mehr viel übrig, dass eine Sammlung unterstützt, dass ein zählbaren nicht -. Nur Count und Contains, glaube ich

Wenn die Verbraucher der Klasse wirklich Elemente müssen behandeln, wie sie in einer Sammlung sind, ist es einfach genug, um einen IEnumerable zu List<T> Konstruktor zu übergeben.

Zurück a T []:

private ICollection<T> items;

public T[] Items
{
    get { return new List<T>(items).ToArray(); }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top