C# 是否有任何内置的收集类型或iQualityComparer<;T>;对于集合,哪个集合基于其中的项目?
框架中的C# 是否有任何内置的收集类型或iQualityComparer<;T>;对于集合,哪个集合基于其中的项目?,c#,.net,collections,equality,iequalitycomparer,C#,.net,Collections,Equality,Iequalitycomparer,框架中的IEnumerable是否有任何内置的集合类型(IEnumerable)或IEqualityComparer,其等于(并相应地GetHashCode)由其中项的相等性定义 比如: var x = new SomeCollection { 1, 2, 3 }; var y = new SomeCollection { 1, 2, 3 }; // so that x.Equals(y) -> true // and x.Shuffle().Equals(y) -> false
IEnumerable
是否有任何内置的集合类型(IEnumerable
)或IEqualityComparer
,其等于(并相应地GetHashCode
)由其中项的相等性定义
比如:
var x = new SomeCollection { 1, 2, 3 };
var y = new SomeCollection { 1, 2, 3 };
// so that x.Equals(y) -> true
// and x.Shuffle().Equals(y) -> false
或者
class-SomeComparer:EqalityComparer{}
//所以
var x=新的[]{1,2,3};
var y=new[]{1,2,3};
//给予
//新的SomeComparer().Equals(x,y)->true
//新的SomeComparer().Equals(x.Shuffle(),y)->false
??我的问题是,框架中是否有类似于代码中所示的SomeCollection
或SomeComparer
的行为
我需要它的原因:因为我有一个字典
的例子,其中键
部分应该是一个集合,它的相等性基于它的条目
要求:
集合只需是具有Add
方法的简单可枚举类型
物品的顺序很重要
集合中可能存在重复项
注意:我可以自己写一本,很简单。关于这一点,有很多问题需要解答。我在问框架本身是否有类。我不相信这样的东西存在。我需要比较两本字典的内容是否相等,不久前我写了这篇文章
public class DictionaryComparer<TKey, TValue> : EqualityComparer<IDictionary<TKey, TValue>>
{
public DictionaryComparer()
{
}
public override bool Equals(IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y)
{
// early-exit checks
if (object.ReferenceEquals(x, y))
return true;
if (null == x || y == null)
return false;
if (x.Count != y.Count)
return false;
// check keys are the same
foreach (TKey k in x.Keys)
if (!y.ContainsKey(k))
return false;
// check values are the same
foreach (TKey k in x.Keys)
{
TValue v = x[k];
if (object.ReferenceEquals(v, null))
return object.ReferenceEquals(y[k], null);
if (!v.Equals(y[k]))
return false;
}
return true;
}
public override int GetHashCode(IDictionary<TKey, TValue> obj)
{
if (obj == null)
return 0;
int hash = 0;
foreach (KeyValuePair<TKey, TValue> pair in obj)
{
int key = pair.Key.GetHashCode(); // key cannot be null
int value = pair.Value != null ? pair.Value.GetHashCode() : 0;
hash ^= ShiftAndWrap(key, 2) ^ value;
}
return hash;
}
private static int ShiftAndWrap(int value, int positions)
{
positions = positions & 0x1F;
// Save the existing bit pattern, but interpret it as an unsigned integer.
uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
// Preserve the bits to be discarded.
uint wrapped = number >> (32 - positions);
// Shift and wrap the discarded bits.
return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}
}
公共类字典比较程序:EqualityComparer
{
公共词典比较程序()
{
}
公共覆盖布尔等于(IDictionary x,IDictionary y)
{
//提前出境检查
if(object.ReferenceEquals(x,y))
返回true;
if(null==x | | y==null)
返回false;
如果(x.Count!=y.Count)
返回false;
//检查钥匙是否相同
foreach(x.Keys中的tk键)
如果(!y.ContainsKey(k))
返回false;
//检查值是否相同
foreach(x.Keys中的tk键)
{
t值v=x[k];
if(object.ReferenceEquals(v,null))
返回object.ReferenceEquals(y[k],null);
如果(!v.等于(y[k]))
返回false;
}
返回true;
}
公共覆盖int GetHashCode(IDictionary obj)
{
if(obj==null)
返回0;
int hash=0;
foreach(obj中的KeyValuePair对)
{
int key=pair.key.GetHashCode();//key不能为null
int value=pair.value!=null?pair.value.GetHashCode():0;
hash^=ShiftAndWrap(键,2)^值;
}
返回散列;
}
私有静态int ShiftAndWrap(int值、int位置)
{
位置=位置&0x1F;
//保存现有位模式,但将其解释为无符号整数。
uint number=BitConverter.ToUInt32(BitConverter.GetBytes(值),0);
//保留要丢弃的位。
uint wrapped=编号>>(32位);
//移位并包装丢弃的位。
返回BitConverter.ToInt32(BitConverter.GetBytes)((数字请保持简单。只需使用接受专用IEqualityComparer的字典选择器(只需在比较器中实现相等逻辑),就可以了。不需要特殊的集合类型等等
如果可以,请参见,最好定义自己的不可变集合类,该类接受IEqualityComparer
作为构造函数参数,并使其等于和GetHashCode()
成员链接到基础集合的成员,而不是为此目的尝试定义一个IEqualityComparer
。除此之外,您的不可变集合类将能够缓存其自身的哈希值,以及其中包含的项的哈希值。这不仅会加快对GetHashCod的调用e()
,但也要对两个集合进行比较。如果两个集合的哈希代码不相等,则无需进一步检查;即使两个集合的哈希代码相等,在测试项本身是否相等之前,也可能需要检查相应项的哈希代码是否匹配[请注意,一般来说,在检查相等性之前使用哈希代码测试作为早期退出并不特别有用,因为最慢的等于
情况(项目匹配时)是散列码无论如何都要匹配的一个;但是,在这里,如果除最后一个项之外的所有项都匹配,则在花时间详细检查每个项之前,测试这些项的散列码可能会发现不匹配
从.NET 4.0开始,可以编写一个IEqualityComparer
,通过使用ConditionalWeakTable
将集合映射到缓存有关它们的信息的对象,从而实现缓存哈希值的不可变集合类的性能优势。尽管如此,除非我们无法作为一个自定义的不可变集合类,我认为在这种情况下,这样一个类可能比一个IEqualityComparer
更好。它似乎与@wdosanjos完全不同。我只是浏览了这个链接。这个问题是关于如何比较任意两个集合的相等性。我的问题是,是否有这样的集合此外,在链接的问题中,顺序并不重要。您在寻找吗?从HashSet.CreateSetComparer()获得的比较器
与您的要求非常接近,只是出于明显的原因,哈希集不保留项的顺序。不,框架中没有此类。这似乎很有用,但为什么要循环x的键两次?您不能将y是否具有x的每个键的检查与其关联项的检查合并起来吗
public class DictionaryComparer<TKey, TValue> : EqualityComparer<IDictionary<TKey, TValue>>
{
public DictionaryComparer()
{
}
public override bool Equals(IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y)
{
// early-exit checks
if (object.ReferenceEquals(x, y))
return true;
if (null == x || y == null)
return false;
if (x.Count != y.Count)
return false;
// check keys are the same
foreach (TKey k in x.Keys)
if (!y.ContainsKey(k))
return false;
// check values are the same
foreach (TKey k in x.Keys)
{
TValue v = x[k];
if (object.ReferenceEquals(v, null))
return object.ReferenceEquals(y[k], null);
if (!v.Equals(y[k]))
return false;
}
return true;
}
public override int GetHashCode(IDictionary<TKey, TValue> obj)
{
if (obj == null)
return 0;
int hash = 0;
foreach (KeyValuePair<TKey, TValue> pair in obj)
{
int key = pair.Key.GetHashCode(); // key cannot be null
int value = pair.Value != null ? pair.Value.GetHashCode() : 0;
hash ^= ShiftAndWrap(key, 2) ^ value;
}
return hash;
}
private static int ShiftAndWrap(int value, int positions)
{
positions = positions & 0x1F;
// Save the existing bit pattern, but interpret it as an unsigned integer.
uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
// Preserve the bits to be discarded.
uint wrapped = number >> (32 - positions);
// Shift and wrap the discarded bits.
return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}
}