Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否有任何内置的收集类型或iQualityComparer<;T>;对于集合,哪个集合基于其中的项目?_C#_.net_Collections_Equality_Iequalitycomparer - Fatal编程技术网

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