C# 即使键或值是引用类型,如何按值比较两个字典?

C# 即使键或值是引用类型,如何按值比较两个字典?,c#,list,dictionary,equals,C#,List,Dictionary,Equals,我想比较两本字典。无论KeyValuePairs顺序如何,都应比较字典。在评论中,建议先对值进行排序,然后使用SequenceEquals,但我不确定如何对词典进行排序(此外,即使对列表进行排序也会有所帮助,据我所知,这是不可能的,因为列表的泛型类型不能保证是IComparable) 当我尝试使用Equals方法时,我总是得到false,因为它检查列表是否为引用相等。我希望它检查列表s的值是否相等。如何做到这一点 例如,假设我有以下字典: var dictionary1 = new Dictio

我想比较两本
字典
。无论
KeyValuePair
s顺序如何,都应比较字典。在评论中,建议先对值进行排序,然后使用
SequenceEquals
,但我不确定如何
对词典进行排序(此外,即使对
列表进行排序也会有所帮助,据我所知,这是不可能的,因为列表的泛型类型不能保证是
IComparable

当我尝试使用
Equals
方法时,我总是得到
false
,因为它检查
列表是否为引用相等。我希望它检查
列表
s的值是否相等。如何做到这一点

例如,假设我有以下字典:

var dictionary1 = new Dictionary<Day, List<WorkSession>>
{
    { Day.Tuesday, new List<WorkSession>() { new WorkSession("22:00", "00:00") } },
    { Day.Monday, new List<WorkSession>() { new WorkSession("20:00", "00:00") } },
    { Day.Sunday, new List<WorkSession>() { new WorkSession("10:00", "00:00") } }
};

var dictionary2 = new Dictionary<Day, List<WorkSession>>
{
    { Day.Sunday, new List<WorkSession>() { new WorkSession("10:00", "00:00") } },
    { Day.Monday, new List<WorkSession>() { new WorkSession("20:00", "00:00") } },
    { Day.Tuesday, new List<WorkSession>() { new WorkSession("22:00", "00:00") } }
};
var字典1=新字典
{
{星期二,新列表(){新工作时段(“22:00”,“00:00”)},
{星期一,新列表(){新工作时段(“20:00”,“00:00”)},
{Day.Sunday,new List(){new WorkSession(“10:00”,“00:00”)}
};
var dictionary2=新字典
{
{Day.Sunday,new List(){new WorkSession(“10:00”,“00:00”)},
{星期一,新列表(){新工作时段(“20:00”,“00:00”)},
{星期二,新列表(){新工作时段(“22:00”,“00:00”)}
};
工作时间:

class WorkSession : IEquatable<WorkSession>
{
    public string Entrance { get; private set; }
    public string Exit { get; private set; }

    public WorkSession(string entrance, string exit)
    {
        Entrance = entrance;
        Exit = exit;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as WorkSession);
    }
    public bool Equals(WorkSession other)
    {
        return other != null &&
               Entrance == other.Entrance &&
               Exit == other.Exit;
    }
    public override int GetHashCode()
    {
        var hashCode = 1257807568;
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Entrance);
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Exit);
        return hashCode;
    }

    public static bool operator ==(WorkSession session1, WorkSession session2)
    {
        return EqualityComparer<WorkSession>.Default.Equals(session1, session2);
    }
    public static bool operator !=(WorkSession session1, WorkSession session2)
    {
        return !(session1 == session2);
    }
}
类工作会话:IEquatable
{
公共字符串入口{get;private set;}
公共字符串出口{get;private set;}
公共工作会话(字符串入口、字符串出口)
{
入口=入口;
退出=退出;
}
公共覆盖布尔等于(对象对象对象)
{
返回等于(obj作为工作会话);
}
公共布尔等于(工作会话其他)
{
返回其他!=null&&
入口=其他入口&&
Exit==其他.Exit;
}
公共覆盖int GetHashCode()
{
var hashCode=1257807568;
hashCode=hashCode*-1521134295+EqualityComparer.Default.GetHashCode(入口);
hashCode=hashCode*-1521134295+EqualityComparer.Default.GetHashCode(退出);
返回哈希码;
}
公共静态布尔运算符==(工作会话会话1,工作会话会话2)
{
返回EqualityComparer.Default.Equals(会话1,会话2);
}
公共静态布尔运算符!=(工作会话会话1,工作会话会话2)
{
return!(session1==session2);
}
}

我想要两个比较这些字典,结果应该是
True
。我怎样才能做到这一点呢?

这里有一些粗制滥造的东西,可以让你开始学习。您需要考虑一些边缘情况,并相应地调整代码

    class Program
    {
        static void Main(string[] args)
        {
            var x = new Dictionary<SomeClass, List<AnotherClass>>();
            var y = new Dictionary<SomeClass, List<AnotherClass>>();

            x.Add(new SomeClass { SomeNumericProperty = 1 }, new List<AnotherClass> { new AnotherClass { SomeStringProperty = "1" } });
            y.Add(new SomeClass { SomeNumericProperty = 1 }, new List<AnotherClass> { new AnotherClass { SomeStringProperty = "1" } });

            var w = new MyCustomComparer();
            var z = w.Equals(x, y);
        }
    }

    public class MyCustomComparer : IEqualityComparer<Dictionary<SomeClass, List<AnotherClass>>>
    {
        public bool Equals(Dictionary<SomeClass, List<AnotherClass>> x, Dictionary<SomeClass, List<AnotherClass>> y)
        {
            var keysAreEqual = x.Keys.OrderBy(o => o.GetHashCode()).SequenceEqual(y.Keys.OrderBy(o => o.GetHashCode()));
            var valuesAreEqual = x.SelectMany(o => o.Value).OrderBy(o => o.GetHashCode()).SequenceEqual(y.SelectMany(o => o.Value).OrderBy(o => o.GetHashCode()));

            return keysAreEqual && valuesAreEqual;
        }

        public int GetHashCode(Dictionary<SomeClass, List<AnotherClass>> obj)
        {
            throw new NotImplementedException();
        }
    }

    public class AnotherClass
    {
        protected bool Equals(AnotherClass other)
        {
            return string.Equals(SomeStringProperty, other.SomeStringProperty);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj.GetType() != this.GetType())
            {
                return false;
            }

            return Equals((AnotherClass)obj);
        }

        public override int GetHashCode()
        {
            int hash = 13;
            hash = (hash * 7) + SomeStringProperty.GetHashCode();
            return hash;
        }

        public string SomeStringProperty { get; set; }
    }

    public class SomeClass
    {
        public int SomeNumericProperty { get; set; }

        protected bool Equals(SomeClass other)
        {
            return SomeNumericProperty == other.SomeNumericProperty;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj.GetType() != this.GetType())
            {
                return false;
            }

            return Equals((SomeClass)obj);
        }

        public override int GetHashCode()
        {
            int hash = 13;
            hash = (hash * 7) + SomeNumericProperty.GetHashCode();
            return hash;
        }
    }
类程序
{
静态void Main(字符串[]参数)
{
var x=新字典();
var y=新字典();
x、 添加(新SomeClass{SomeNumericProperty=1},新列表{new AnotherClass{SomeStringProperty=“1”});
y、 添加(新SomeClass{SomeNumericProperty=1},新列表{new AnotherClass{SomeStringProperty=“1”});
var w=新的MyCustomComparer();
var z=w等于(x,y);
}
}
公共类MyCustomComparer:IEqualityComparer
{
公共布尔等于(字典x、字典y)
{
var keysAreEqual=x.Keys.OrderBy(o=>o.GetHashCode()).SequenceEqual(y.Keys.OrderBy(o=>o.GetHashCode());
var valuesAreEqual=x.SelectMany(o=>o.Value).OrderBy(o=>o.GetHashCode()).SequenceEqual(y.SelectMany(o=>o.Value).OrderBy(o=>o.GetHashCode());
返回键相等&值相等;
}
公共int GetHashCode(字典obj)
{
抛出新的NotImplementedException();
}
}
公共类另一类
{
受保护布尔等于(另一类其他)
{
返回string.Equals(SomeStringProperty,other.SomeStringProperty);
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(null,obj))
{
返回false;
}
if(ReferenceEquals(this,obj))
{
返回true;
}
如果(obj.GetType()!=this.GetType())
{
返回false;
}
返回等于((另一类)obj);
}
公共覆盖int GetHashCode()
{
int hash=13;
hash=(hash*7)+SomeStringProperty.GetHashCode();
返回散列;
}
公共字符串SomeStringProperty{get;set;}
}
公共类
{
公共int SomeNumericProperty{get;set;}
受保护布尔等于(某类其他)
{
返回SomeNumericProperty==other.SomeNumericProperty;
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(null,obj))
{
返回false;
}
if(ReferenceEquals(this,obj))
{
返回true;
}
如果(obj.GetType()!=this.GetType())
{
返回false;
}
返回等于((SomeClass)obj);
}
公共覆盖int GetHashCode()
{
int hash=13;
hash=(hash*7)+SomeNumericProperty.GetHashCode();
返回散列;
}
}

这里有一些粗制滥造的东西可能会让你开始学习。您需要考虑一些边缘情况,并相应地调整代码

    class Program
    {
        static void Main(string[] args)
        {
            var x = new Dictionary<SomeClass, List<AnotherClass>>();
            var y = new Dictionary<SomeClass, List<AnotherClass>>();

            x.Add(new SomeClass { SomeNumericProperty = 1 }, new List<AnotherClass> { new AnotherClass { SomeStringProperty = "1" } });
            y.Add(new SomeClass { SomeNumericProperty = 1 }, new List<AnotherClass> { new AnotherClass { SomeStringProperty = "1" } });

            var w = new MyCustomComparer();
            var z = w.Equals(x, y);
        }
    }

    public class MyCustomComparer : IEqualityComparer<Dictionary<SomeClass, List<AnotherClass>>>
    {
        public bool Equals(Dictionary<SomeClass, List<AnotherClass>> x, Dictionary<SomeClass, List<AnotherClass>> y)
        {
            var keysAreEqual = x.Keys.OrderBy(o => o.GetHashCode()).SequenceEqual(y.Keys.OrderBy(o => o.GetHashCode()));
            var valuesAreEqual = x.SelectMany(o => o.Value).OrderBy(o => o.GetHashCode()).SequenceEqual(y.SelectMany(o => o.Value).OrderBy(o => o.GetHashCode()));

            return keysAreEqual && valuesAreEqual;
        }

        public int GetHashCode(Dictionary<SomeClass, List<AnotherClass>> obj)
        {
            throw new NotImplementedException();
        }
    }

    public class AnotherClass
    {
        protected bool Equals(AnotherClass other)
        {
            return string.Equals(SomeStringProperty, other.SomeStringProperty);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj.GetType() != this.GetType())
            {
                return false;
            }

            return Equals((AnotherClass)obj);
        }

        public override int GetHashCode()
        {
            int hash = 13;
            hash = (hash * 7) + SomeStringProperty.GetHashCode();
            return hash;
        }

        public string SomeStringProperty { get; set; }
    }

    public class SomeClass
    {
        public int SomeNumericProperty { get; set; }

        protected bool Equals(SomeClass other)
        {
            return SomeNumericProperty == other.SomeNumericProperty;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj.GetType() != this.GetType())
            {
                return false;
            }

            return Equals((SomeClass)obj);
        }

        public override int GetHashCode()
        {
            int hash = 13;
            hash = (hash * 7) + SomeNumericProperty.GetHashCode();
            return hash;
        }
    }
类程序
{
静态void Main(字符串[]参数)
{
var x=新字典();
var y=新字典();
x、 添加(新SomeClass{SomeNumericProperty=1},新列表{new AnotherClass{SomeStringProperty=“1”});
y、 加