【问题标题】:Immutable set in .NET.NET 中的不可变集
【发布时间】:2011-05-06 21:33:10
【问题描述】:

.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);

这种用法高度不透明,难以优化和理解。有没有更好的方法可以在不编写自定义功能集类型的情况下做到这一点?

【问题讨论】:

标签: c# set immutability functional-programming


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    更新

    这个答案是前段时间写的,从那时起,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 在 cmets 中所提到的,使用 Concat 会产生相同的结果并且可能表现更好:

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

    【讨论】:

    • 此代码不保证深度不变性。如果您修改集合结构(例如集合中包含的内容),则原始集合结构将保持不变。但是如果你修改结果集中的项目,原始集中的项目也会改变。
    • 只有在集合中的项目本身不可变的情况下,C# 才能保证深度不变性。集合不能自行强制执行。另外,HashSet 是一个可变集合,所以也许你应该寻找 BCL 之外的其他类。
    • @MerlynMorgan-Graham:某种类对象类型的不可变集合的状态是由此引用的对象的身份的集合。如果我有一份印在防篡改纸上的五辆汽车的车辆识别号列表,它总是指相同的五辆汽车。该列表不应被视为说明汽车的位置、颜色、行驶里程等。汽车的所有这些特征都是可变的。然而,汽车的许多属性都可以改变这一事实并没有降低汽车列表的不可变性。
    • @Jordão,超级猫:当然。只是想明确指出,将项目置于“不可变的 Set 类型”(正如 OP 所要求的那样)并没有使它们也神奇地不可变。他没有问这个问题,但我认为对于那些不太熟悉 .Net 中的不变性的人来说,这是一个合理的后续想法。
    • @MerlynMorgan-Graham:是的,这是澄清的好点:-)
    【解决方案3】:

    有一个ReadOnlyCollection,但它不是哈希表。 LINQ 添加了Union 方法作为扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2012-01-07
      • 2016-10-02
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多