如何知道 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()
方法。您问题中的代码显然不是您的实际代码...
我有一个 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()
方法。您问题中的代码显然不是您的实际代码...