2010-11-08 15 views
6

¿El .NET BCL tiene un tipo de conjunto inmutable? Estoy de programación en un dialecto funcional de C# y me gustaría hacer algo comoConjunto inmutable en .NET

new Set.UnionWith(A).UnionWith(B).UnionWith(C) 

Pero lo mejor que puedo encontrar es HashSet.UnionWith, lo que requeriría la siguiente secuencia de llamadas:

HashSet composite = new HashSet(); 
composite.UnionWith(A); 
composite.UnionWith(B); 
composite.UnionWith(C); 

Este el uso es altamente opaco desde el punto de vista referencial, lo que dificulta su optimización y comprensión. ¿Hay una forma mejor de hacerlo sin escribir un tipo de conjunto funcional personalizado?

+0

Esto también puede estar relacionado http: // stackoverflow.com/questions/927181/inmutable-collections – R0MANARMY

Respuesta

4

actualización

Esta respuesta fue escrito hace algún tiempo, y desde entonces una serie de colecciones inmutables se han introducido en el espacio de nombres System.Collections.Immutable.

Respuesta original

Puede lanzar su propio método para esto:

public static class HashSetExtensions { 
    public static HashSet<T> Union<T>(this HashSet<T> self, HashSet<T> other) { 
    var set = new HashSet<T>(self); // don't change the original set 
    set.UnionWith(other); 
    return set; 
    } 
} 

utilizar de esta manera:

var composite = A.Union(B).Union(C); 

También puede utilizar LINQ's Union, pero para llegar un conjunto, deberá pasar el resultado al constructor HashSet:

var composite = new HashSet<string>(A.Union(B).Union(C)); 

Pero, HashSet es mutable. Puede intentar usar F#'s immutable set.

Además, como se ha mencionado en los comentarios por ErikE, utilizando Concat da el mismo resultado y probablemente tiene un mejor rendimiento:

var composite = new HashSet<string>(A.Concat(B).Concat(C)); 
+2

Este código no garantiza la inmutabilidad profunda. Si modifica la estructura establecida (por ejemplo, lo que está contenido en el conjunto), la estructura del conjunto original estará intacta. Pero si modifica los elementos en el conjunto resultante, los elementos en el conjunto original también se cambiarán. –

+2

La inmutabilidad profunda solo está garantizada en C# si los elementos del conjunto son inmutables. El conjunto no puede imponerlo por sí mismo. Además, el 'HashSet' es un conjunto mutable, por lo que quizás debería buscar otras clases fuera del BCL. –

+2

@ MerlynMorgan-Graham: El estado de un conjunto inmutable de algún tipo de clase-objeto es la colección de las identidades de los objetos a los que se hace referencia. Si tengo una lista de los números de identificación de vehículos de cinco autos impresos en papel a prueba de falsificaciones, siempre se referirá a los mismos cinco autos. No se debe considerar que la lista dice nada sobre dónde están los automóviles, de qué color son, cuántas millas han conducido, etc. Todas esas características de los automóviles son mutables. El hecho de que muchas propiedades de un automóvil pueden cambiar, sin embargo, no hace que la lista de autos sea menos inmutable. – supercat

9

El nuevo ImmutableCollections tienen:

  • ImmutableStack<T>
  • ImmutableQueue<T>
  • ImmutableList<T>
  • ImmutableHashSet<T>
  • ImmutableSortedSet<T>
  • ImmutableDictionary<K, V>
  • ImmutableSortedDictionary<K, V>

Más información here

Acerca de la unión pasa esta prueba:

[Test] 
public void UnionTest() 
{ 
    var a = ImmutableHashSet.Create("A"); 
    var b = ImmutableHashSet.Create("B"); 
    var c = ImmutableHashSet.Create("C"); 
    var d = a.Union(b).Union(c); 
    Assert.IsTrue(ImmutableHashSet.Create("A", "B", "C").SetEquals(d)); 
}