2010-08-31 4 views
5

Ich habe vor kurzem begonnen, F # für "echte Arbeit" zu verwenden und die Schönheit von unveränderlichen Datenstrukturen wie den diskriminierten Vereinigungen und Aufzeichnungen in F # wiederzuentdecken. Ich habe auch festgestellt, dass sie für C# sehr einfach zu verwenden sind, zumal sie keine direkten Abhängigkeiten von der F # -Laufzeit benötigen. Wenn es jedoch darum geht, Listen in diesen Strukturen darzustellen, habe ich noch keine ideale Lösung gefunden.Was ist die beste Möglichkeit, eine unveränderbare Liste in .NET darzustellen?

Mein erster Versuch war, die Listen als Seq < ‚a> (IEnumerable in der C# Welt) zu geben, die für Mutieren der Sammlung alle Methoden ohne Export der Weg ICollection eine schöne allgemeine Sammlung Schnittstelle bietet <> und seine Freunde tut. Da ich jedoch den Konstruktor einer diskriminierten Union oder eines diskriminierten Datensatzes nicht kontrollieren kann, ist es für den Ersteller einer Instanz dieser Typen möglich, eine IEnumerable-Implementierung bereitzustellen, die sich bei Verwendung ändern oder auslösen kann (z. B. ein LINQ-Ausdruck). . IEnumerable <> wird mir deshalb keine Hilfe vom Compiler geben, um zu beweisen, dass der Wert unveränderlich und daher threadsicher ist.

Meine aktuelle Strategie besteht darin, den F # Listentyp zu verwenden, der eine unveränderbare Sammlung garantiert, aber eine Abhängigkeit von der F # -Laufzeit hinzufügt und bei Verwendung aus nicht F # -Projekten ein wenig ausschaut. Es erlaubt jedoch eine F # Mustererkennung, die IEnumerable < nicht tut. Es gibt auch keine Wahl in der tatsächlichen Darstellung einer Liste, und in einigen Fällen (wie große Listen von primitiven Werten) passt die F # -Listendarstellung nicht wirklich.

Was ich wirklich gerne sehen würde, ist ein unveränderlicher Array-Typ in .NET, der genauso kompakt wie das normale Array dargestellt wird, aber mit einer Compiler-Garantie, dass er nicht mutiert wird. Ich würde const wie in C++ begrüßen, obwohl es wahrscheinlich nicht sehr wahrscheinlich ist. Gibt es noch eine andere Option, die ich verpasst habe?

+0

Nicht einmal F # Listen sind wirklich wirklich unumstößlich, Sie können sie an Ort und Stelle mit Reflektion mutieren (siehe http://de.wikibooks.org/wiki/F_Sharp_Programming/Reflection);) – Juliet

+1

siehe auch http: // stackoverflow .com/questions/3485262/efficient-immutable-extensible-collections-for-net –

+2

Ich würde auch einen zeit- und platzsparenden unveränderlichen Array-Typ lieben; Wir denken darüber nach, die Sprach- und Laufzeitarbeit zu leisten, um es in einer * hypothetischen * zukünftigen Version von C# zu realisieren, aber leider wird es wahrscheinlich nicht über der Mitte der Prioritätenliste landen. (Denken Sie daran, dass alle Überlegungen von Eric über fiktionale Features ohne Budgets, die in unangemeldeten Produkten implementiert sind, nur Unterhaltungszwecken dienen.) –

Antwort

7

Wenn das, was Sie wollen, ist ein unveränderliches Array Implementierung dann können Sie nur so etwas wie die folgenden

public sealed class ImmutableArray<T> : IEnumerable<T>{ 
    private readonly T[] m_array; 
    public T this[int index] { 
    get { return m_array[index]; } 
    } 
    public int Length { 
    get { return m_array.Length; } 
    } 
    public ImmutableArray(IEnumerable<T> enumerable) { 
    m_array = enumerable.ToArray(); 
    } 
    // IEnumerable<T> implementation ommitted 
} 
+0

Das könnte tatsächlich der beste Weg sein. Der Konstruktor müsste das Array kopieren, aber zumindest könnte man eine Instanz dieses Typs frei herumreichen und wissen, dass es seinen Inhalt nicht ändern würde. – SoftMemes

2

verwenden Wickeln Sie Ihr normales Array in einem ReadOnlyCollection<T> Beispiel:

var readOnlyData = new ReadOnlyCollection<TheType>(theRealCollection); 

(Hinweis, dies tut Kopieren Sie nicht die zugrunde liegende Sammlung, sondern enthält eine Referenz und und ändernde Mitglieder von IList<T> usw. sind implementiert, um eine Ausnahme auszulösen.)

+0

Ich müsste die Eigenschaften statisch als ReadOnlyCollection <> eingeben, was möglich ist, bietet aber keinen Vorteil gegenüber der Eingabe als IEnumerable <>, da der Ersteller immer noch eine ReadOnlyCollection bereitstellen kann, die von einer nicht veränderbaren Auflistung unterstützt wird. ReadOnlyCollection <> implementiert auch eine Reihe von Schnittstellen, die eine unveränderbare Sammlung nicht unterstützen sollte. – SoftMemes

+0

Das Problem mit 'ReadOnlyCollection ' obwohl es nicht unveränderlich ist, es ist nur readonly. – JaredPar

1

Ich würde empfehlen, Eric Lippert's Serie auf immutability zu betrachten, es ist eine sehr nützliche Lese. Teil 4 über eine immutable queue wäre ein guter Anfang.

+0

Das Problem ist, dass meine Implementierung einer unveränderlichen Warteschlange nicht annähernd so platzsparend ist wie ein Array. Ein Array von beispielsweise Bytes nimmt ein Byte pro Element ein. Eine Warteschlange von Bytes nimmt Dutzende von Bytes pro Element auf. –

+0

Guter Punkt, ich habe nicht darüber nachgedacht, danke für die Info. –

+0

Obwohl Erics Blog definitiv interessant ist, was ich wirklich suchte, war eine vorhandene Datenstruktur, um unveränderliche Listen zu vertreten, nicht, wie man eine unveränderliche Liste oder eine der anspruchsvolleren unveränderlichen Datenstrukturen implementiert. – SoftMemes