.NET中的不可变集

Dav*_*cht 6 c# functional-programming set immutability

.NET BCL是否具有不可变的Set类型?我正在编写一个C#的功能方言,并希望做类似的事情

new Set.UnionWith(A).UnionWith(B).UnionWith(C)
Run Code Online (Sandbox Code Playgroud)

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

HashSet composite = new HashSet();
composite.UnionWith(A);
composite.UnionWith(B);
composite.UnionWith(C);
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*son 11

新的ImmutableCollections有:

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

更多信息在这里

关于工会,这个测试通过:

[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));
}
Run Code Online (Sandbox Code Playgroud)


Jor*_*dão 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

var composite = A.Union(B).Union(C);
Run Code Online (Sandbox Code Playgroud)

你也可以使用LINQUnion,但要获得一个集合,你需要将结果传递给HashSet构造函数:

var composite = new HashSet<string>(A.Union(B).Union(C));
Run Code Online (Sandbox Code Playgroud)

但是,HashSet它本身是可变的.您可以尝试使用F#的不可变集.

此外,正如ErikE的评论中所提到的,使用Concat产生相同的结果并且可能表现更好:

var composite = new HashSet<string>(A.Concat(B).Concat(C));
Run Code Online (Sandbox Code Playgroud)

  • 此代码不保证深层不变性.如果修改集合结构(例如集合中包含的内容),原始集合结构将保持不变.但是,如果您修改结果集中的项目,原始集合中的项目也将更改. (2认同)
  • 如果集合中的项目本身是不可变的,则只能在C#中保证深层不变性.该集合无法自行实施.另外,`HashSet`是一个可变集,所以也许你应该寻找BCL之外的其他类. (2认同)
  • @MerlynMorgan-Graham:某个类对象类型的不可变集的状态是由此引用的对象的标识的集合.如果我在防拆纸上印有五辆汽车的车辆识别号码清单,它将始终指向相同的五辆汽车.这份清单不应该被视为关于汽车在哪里,它们是什么颜色,它们驱动了多少里程等等.汽车的所有特性都是可变的.然而,汽车的许多属性可以改变的事实并不会使汽车列表变得不那么不可变. (2认同)