.NET中的不可变集

时间:2010-11-08 21:07:14

标签: c# set immutability functional-programming

.NET BCL是否具有不可变的Set类型?我正在使用C#的功能方言进行编程,并希望做类似

的操作
new Set.UnionWith(A).UnionWith(B).UnionWith(C)

但我能找到的最好的是HashSet.UnionWith,这需要以下一系列调用:

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

这种用法高度引用不透明,使其难以优化和理解。如果没有编写自定义功能集类型,有没有更好的方法呢?

3 个答案:

答案 0 :(得分:10)

新的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));
}

答案 1 :(得分:5)

<强>更新

这个答案是在不久前编写的,从那时起,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 :(得分:0)

ReadOnlyCollection,但它不是哈希表。 LINQ将Union方法添加为扩展名。