比较c#中两个相同数据的词典?

mez*_*hic 15 c# .net-3.5

我有两个字典包含一个字符串键,然后是一个对象.该对象包含五个字段.是否有一种优雅的方法可以确保两个字典首先包含相同的键,然后如果这是正确的,每个对象包含相同的五个字段?

这两个词典是否具有相同的内置哈希码或其他东西?

编辑,似乎不适用于以下代码:

Dictionary<string, MyClass> test1 = new Dictionary<string, MyClass>();
Dictionary<string, MyClass> test2 = new Dictionary<string, MyClass>();

MyClass i = new MyClass("", "", 1, 1, 1, 1);
MyClass j = new MyClass("", "", 1, 1, 1, 1);

test1.Add("1", i);
test2.Add("1", j);

bool equal = test1.OrderBy(r => r.Key).SequenceEqual(test2.OrderBy(r => r.Key));

class MyClass
{
    private string a;
    private string b;
    private long? c;
    private decimal d;
    private decimal e;
    private decimal f;

    public MyClass(string aa, string bb, long? cc, decimal dd, decimal ee, decimal ff)
    {
        a= aa;
        b= bb;
        c= cc;
        d= dd;
        e= ee;
        f= ff;
    }
Run Code Online (Sandbox Code Playgroud)

这返回false?

Raw*_*ing 21

您可以使用

bool dictionariesEqual = 
    dic1.Keys.Count == dic2.Keys.Count &&
    dic1.Keys.All(k => dic2.ContainsKey(k) && object.Equals(dic2[k], dic1[k]));
Run Code Online (Sandbox Code Playgroud)

  • dic2 [k] == dic1 [k]如果值是引用类型,那么它将仅比较引用,而不是精确值。(字段) (2认同)

Hab*_*bib 18

首先,您必须在类中重写EqualsGetHashCode方法,否则将对引用而不是实际值进行比较.(要覆盖的代码EqualsGetHashCode在末尾提供),之后您可以使用:

var result = (dic1 == dic2) || //Reference comparison (if both points to same object)
             (dic1.Count == dic2.Count && !dic1.Except(dic2).Any());
Run Code Online (Sandbox Code Playgroud)

由于返回Dictionary中的项目顺序是未定义的,因此您不能依赖Dictionary.SequenceEqual (不OrderBy).

你可以试试:

Dictionary<string, object> dic1 = new Dictionary<string, object>();
Dictionary<string, object> dic2 = new Dictionary<string, object>();
dic1.Add("Key1", new { Name = "abc", Number = "123", Address = "def", Loc = "xyz" });
dic1.Add("Key2", new { Name = "DEF", Number = "123", Address = "def", Loc = "xyz" });
dic1.Add("Key3", new { Name = "GHI", Number = "123", Address = "def", Loc = "xyz" });
dic1.Add("Key4", new { Name = "JKL", Number = "123", Address = "def", Loc = "xyz" });

dic2.Add("Key1",new { Name = "abc",Number=  "123", Address= "def", Loc="xyz"});
dic2.Add("Key2", new { Name = "DEF", Number = "123", Address = "def", Loc = "xyz" });
dic2.Add("Key3", new { Name = "GHI", Number = "123", Address = "def", Loc = "xyz" });
dic2.Add("Key4", new { Name = "JKL", Number = "123", Address = "def", Loc = "xyz" });


bool result = dic1.SequenceEqual(dic2); //Do not use that
Run Code Online (Sandbox Code Playgroud)

大部分时间上面都会返回true,但由于无序的性质,人们不能真正依赖它Dictionary.

既然SequenceEqual会比较顺序,因此 依靠SequenceEqual可能是错误的.你必须用来OrderBy订购两个字典然后使用SequenceEqual如下:

bool result2 = dic1.OrderBy(r=>r.Key).SequenceEqual(dic2.OrderBy(r=>r.Key));
Run Code Online (Sandbox Code Playgroud)

但这将涉及多次迭代,一次用于排序,另一次用于比较每个元素SequenceEqual.

覆盖Equals和代码GetHashCode

private class MyClass
{
    private string a;
    private string b;
    private long? c;
    private decimal d;
    private decimal e;
    private decimal f;

    public MyClass(string aa, string bb, long? cc, decimal dd, decimal ee, decimal ff)
    {
        a = aa;
        b = bb;
        c = cc;
        d = dd;
        e = ee;
        f = ff;
    }

    protected bool Equals(MyClass other)
    {
        return string.Equals(a, other.a) && string.Equals(b, other.b) && c == other.c && e == other.e && d == other.d && f == other.f;
    }

    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((MyClass)obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = (a != null ? a.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (b != null ? b.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ c.GetHashCode();
            hashCode = (hashCode * 397) ^ e.GetHashCode();
            hashCode = (hashCode * 397) ^ d.GetHashCode();
            hashCode = (hashCode * 397) ^ f.GetHashCode();
            return hashCode;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以看到:正确的方法来覆盖Equals()和GetHashCode()