2010-11-08 3 views
6

Имеет ли .NET BCL неизменяемый тип набора? Я программирования в функциональном диалекте C# и хотел бы сделать что-то вродеНеизменяемый набор в .NET

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

Но лучшее, что я могу найти HashSet.UnionWith, что потребует следующую последовательность вызовов:

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

Это использование сильно ссылочно непрозрачно, что затрудняет оптимизацию и понимание. Есть ли лучший способ сделать это без написания настраиваемого типа набора функций?

+0

Это также может быть связанными с http: // stackoverflow.com/questions/927181/immutable-collections – R0MANARMY

ответ

4

Update

Этот ответ был написан некоторое время назад, и с тех пор множество неизменных коллекций были введены в System.Collections.Immutable имен.

Оригинальный ответ

Вы можете раскрутить свой собственный метод для этого:

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; 
    } 
} 

Используйте это так:

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

Вы также можете использовать LINQ's Union, но, чтобы получить набор, вам нужно передать результат в конструктор HashSet:

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

Но, HashSet сам изменен. Вы можете попробовать использовать F#'s immutable set.

Кроме того, как упомянуто в комментарии по ErikE, используя Concat дает тот же результат и, вероятно, работает лучше:

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

Этот код не гарантирует глубокую неизменность. Если вы измените структуру набора (например, то, что содержится в наборе), исходная структура набора будет неповрежденной. Но если вы измените элементы в результирующем наборе, элементы в исходном наборе также будут изменены. –

+2

Глубокая неизменность гарантируется только на C#, если элементы в наборе неизменяемы. Набор не может принудительно выполнять его самостоятельно. Кроме того, 'HashSet' является изменяемым набором, поэтому, возможно, вам следует искать другие классы вне BCL. –

+2

@ MerlynMorgan-Graham: Состояние неизменяемого набора некоторого типа класса-объекта представляет собой совокупность тождеств объектов, на которые ссылается. Если у меня есть список из пяти идентификационных номеров автомобилей, напечатанных на бумаге с вскрытием, это всегда относится к тем же пяти автомобилям. Список не следует рассматривать как что-либо о том, где находятся автомобили, какой цвет они, сколько миль они везли и т. Д. Все эти характеристики автомобилей изменяемы. Однако тот факт, что многие свойства автомобиля могут измениться, не делает список автомобилей менее непреложным. – supercat

9

Новый ImmutableCollections есть:

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

Подробнее here

О союзе этот тест проходит:

[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)); 
} 
Смежные вопросы