如何知道 IEnumerable 是否与其他集合相同?

How to know if the IEnumerable is the same collection than other?

我有一个 class,其中有一个哈希集作为集合。有时我将此哈希集作为参数传递给方法,但参数是 IEnumerable.

在这个方法中,我想检查对象的参数和属性是否是同一个集合,以避免如果集合相同则做任何事情。

class是这样的:

MyClass
{
    HashSet<MyType> MyCollection;

    public void MyMethod(IEnumerable<MyType> param)
    {
       if(this.MyCOllecction != param)
       {
           this.MyCollection.Clear();
           this.MyCollection.AddRange(param);
       }
    }
}

问题是 if 为真,所以它处理集合。问题是最后的结果是 MyCollection 是空的,因为首先我清除了集合所以当 IEnumerable 参数尝试访问集合的元素时,是空的,所以最后的结果是MyCollection 为空。应该是把MyCollection有的元素重新加起来。

我想知道如何知道 IEnumerable 是否可以访问 MyCollection 属性 或另一个不同的集合。

谢谢

问题不明确 - same 可能表示相同的实例或包含相同的数据。原始代码无论如何都行不通,因为 HashSet 没有 AddRange.

替换存储集

一种可能的处理方法是使用模式匹配来检查输入是否是 HashSet 与存储的实例相同的实例:

public void MyMethod(IEnumerable<MyType> param)
{
   if(param is HashSet<MyType> h && h.ReferenceEquals(MyCollection))
   {
       return;
   }
   MyCollection=new HashSet<MyType>(param);
}

合并新值

A HashSet 没有 AddRange,因此原始代码无论如何都不起作用。等效项是 UnionWith,它将添加 个新项目。这比使用 SequenceEquals 然后添加新项目更快,因为 HashSet 针对集合操作进行了优化:

public void MyMethod(IEnumerable<MyType> param)
{
   if(param is HashSet<MyType> h && h.ReferenceEquals(MyCollection))
   {
       return;
   }
   MyCollection.UnionWith(param);
}

无法可靠地优化它,因为无法确定传递给方法的集合与 class.[=16= 持有的集合相同。 ]

您可能认为可以使用 object.Equals() 来检查这一点,这确实适用于 一些 情况 - 但并非适用于所有情况。考虑这段代码:

HashSet<int> hashset = new HashSet<int>();

IEnumerable<int> test1 = hashset;
IEnumerable<int> test2 = hashset;

// Prints "equal"
Console.WriteLine(object.Equals(test1, test2) ? "equal" : "not equal");

test1 = hashset.AsEnumerable();
test2 = hashset.AsEnumerable();

// Prints "equal"
Console.WriteLine(object.Equals(test1, test2) ? "equal" : "not equal");

test1 = hashset;
test2 = hashset.Select(item => item);

// Prints "not equal". Oh dear.
Console.WriteLine(object.Equals(test1, test2) ? "equal" : "not equal");

所以这表明不可能仅仅基于对象引用相等性来可靠地优化它。

此外,您声明元素的数量相当少 - 因此这种优化是不必要的。

如果你真的想安全地优化它,你可以这样做:

public void MyMethod(IEnumerable<MyType> param)
{
    if (!object.Equals(this.MyCollection, param))
    {
        this.MyCollection = new HashSet<MyType>();
        this.MyCollection.AddRange(param);
    }

    // ...
}

但我不认为这种优化真的是必要的,所以你可以这样实现:

public void MyMethod(IEnumerable<MyType> param)
{
    this.MyCollection = new HashSet<MyType>();
    this.MyCollection.AddRange(param);

    // ...
}

您必须在代码中使用实际类型,而不是 HashSet,后者没有 AddRange() 方法。您问题中的代码显然不是您的实际代码...