Frage

Ich habe ein Objekt in einer Multithread-Umgebung, das eine Sammlung von Informationen verwaltet, z. B.:

public IList<string> Data 
{
    get 
    {
        return data;
    }
}

Ich habe derzeit return data; umhüllt von a ReaderWriterLockSlim um die Sammlung vor Verstößen gegen die Weitergabe zu schützen.Um ganz sicher zu gehen, möchte ich die Sammlung jedoch schreibgeschützt zurückgeben, sodass der aufrufende Code keine Änderungen an der Sammlung vornehmen und nur das anzeigen kann, was bereits vorhanden ist.Ist das überhaupt möglich?

War es hilfreich?

Lösung

Wenn Ihr nur Absicht ist, den Code zu bekommen auffordern, nicht einen Fehler zu machen, und die Sammlung ändern, wenn es nur alle notwendigen lesen, das ist eine Schnittstelle zurück, die Hinzufügen von Unterstützung nicht, entfernen, etc .. Warum nicht IEnumerable<string> zurückkehren? Telefonvorwahl würde werfen müssen, was sie zu tun sind unwahrscheinlich, ohne die Interna der Eigenschaft zu wissen, sie zugreifen.

Wenn jedoch Ihre Absicht ist, von dem anrufenden Code zu verhindern, dass Updates von anderen Threads Beobachten Sie zurück zu Lösungen fallen müssen bereits erwähnt, eine tiefe oder flache Kopie je nach Bedarf durchzuführen.

Andere Tipps

Wenn Sie Ihre zugrunde liegenden Daten als Liste gespeichert ist, können Sie List (T) verwenden. AsReadOnly Methode.
Wenn Ihre Daten aufgezählt werden können, können Sie Enumerable.ToList Methode werfen sie Ihre Sammlung zur Liste und rufen AsReadOnly auf sie.

Ich habe für Ihre Antwort akzeptiert und damit einverstanden ist - aber vielleicht gebe ich Ihnen etwas zu prüfen

Sie eine Sammlung nicht direkt zurück. Machen Sie eine genau benannte Business-Logik-Klasse, die den Zweck der Sammlung widerspiegelt.

Der Hauptvorteil dieser kommt in der Tatsache, dass Sie nicht den Code zu Sammlungen so hinzufügen können, wenn Sie eine native „Sammlung“ haben in Ihrem Objektmodell, Sie IMMER nicht-OO-Support-Code in Ihrem Projekt verteilt haben, darauf zuzugreifen .

Zum Beispiel, wenn Sie Ihre Sammlung Rechnungen sind, dann würden Sie wahrscheinlich 3 oder 4 Stellen im Code, wo Sie unbezahlte Rechnungen iteriert. Sie könnten eine getUnpaidInvoices Methode haben. Doch die wirkliche Macht kommt, wenn Sie starten von Methoden zu denken, wie „payUnpaidInvoices (Payer, Konto);“.

Wenn Sie um Sammlungen übergeben, anstatt ein Objektmodell zu schreiben, ganze Klassen von Refactorings werden Sie nie auftreten.

Beachten Sie auch, dass dies macht Ihr Problem besonders schön. Wenn Sie nicht die Leute wollen die Sammlungen zu ändern, braucht Ihr Container keine Mutatoren enthalten. Wenn Sie später entscheiden, dass in nur einem Fall, dass Sie tatsächlich, ihn zu ändern, können Sie einen sicheren Mechanismus schaffen, dies zu tun.

Wie lösen Sie das Problem, wenn Sie um eine native Sammlung sind vorbei?

Auch einheimische Sammlungen können nicht mit zusätzlichen Daten verbessert werden. Sie finden dieses nächste Mal finden erkennen, dass Sie in (Sammlung, Extras) passieren, um mehr als ein oder zwei Methoden. Es zeigt an, dass „Extra“ gehört mit dem Objekt Ihrer Sammlung enthält.

Ich glaube, Sie verwechseln Konzepte hier.

Die ReadOnlyCollection stellt einen Nur-Lese-Wrapper für eine bestehende Sammlung, so dass Sie (Klasse A) einen Verweis auf die Sammlung in dem sicheren Wissen weitergeben, dass der Anrufer (Klasse B) kann die Sammlung nicht ändern (dh kann nicht hinzufügen oder entfernen alle Elemente aus der Auflistung.)

Es gibt absolut keine Thread-Sicherheit gewährleistet.

  • Wenn Sie (Klasse A) weiterhin die zugrunde liegende Auflistung ändern, nachdem Sie es auszuteilen als ReadOnlyCollection dann Klasse B, diese Änderungen sehen, haben alle Iteratoren für ungültig erklärt, usw. und in der Regel zu einem der üblichen Concurrency Probleme offen mit Sammlungen.
  • Außerdem, wenn die Elemente in der Auflistung sind wandelbar, sowohl Sie (Klasse A) und die Anrufer (Klasse B) wird jegliche wandelbaren Zustand der Objekte in der Sammlung ändern kann.

Ihre Umsetzung hängt von Ihren Bedürfnissen:  - Wenn Sie nicht sehen keine weiteren Änderungen an der Sammlung nicht über den Anrufer (Klasse B) kümmern, dann können Sie nur die Sammlung klonen, geben Sie es aus, und fürsorglich stoppen.  - Wenn Sie auf jeden Fall die Anrufer (Klasse B) müssen Änderungen sehen, die auf die Sammlung gemacht werden, und Sie wollen, dass dieser Thread-sicher sein, dann haben Sie eher ein Problem auf der Hand. Eine Möglichkeit ist, Ihre eigene Thread-sichere Variante der Readonlycollection zu implementieren gesperrtem Zugriff zu ermöglichen, obwohl dies wird nicht trivial und nicht performant, wenn Sie IEnumerable unterstützen wollen, und es noch wird nicht schützen Sie gegen wandelbare Elemente in der Sammlung.

sollte man beachten, dass aku 's Antwort wird nur die Liste schützen wie nur gelesen werden. Elemente in der Liste sind nach wie vor sehr beschreibbar. Ich weiß nicht, ob es eine Möglichkeit, den Schutz nicht-atomare Elemente ist, ohne sie zu klonen, bevor sich in der Nur-Lese-Liste setzen.

Sie möchten die Ausbeute Stichwort. Sie Schleife durch die IEnumerable-Liste und gibt die Ergebnisse mit yeild. Dies ermöglicht es dem Verbraucher die für jeden zu verwenden, ohne die Sammlung zu ändern.

Es würde wie folgt aussehen:

List<string> _Data;
public IEnumerable<string> Data
{
  get
  {
    foreach(string item in _Data)
    {
      return yield item;
    }
  }
}

Sie können stattdessen eine Kopie der Sammlung verwenden.

public IList<string> Data {
get {
    return new List<T>(data);
}}

Auf diese Weise spielt es keine Rolle, ob es aktualisiert wird.

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