根据字典比较两个对象的相等性

维基

我有两个具有以下定义的对象:

public static Dictionary<string, Container> cont1 = new Dictionary<string, Container>();
public static Dictionary<string, Container> cont2 = new Dictionary<string, Container>();

Container类的架构如下:

public class Container
{
    public string IDx { get; set; }
    public string IDy { get; set; }
    public string Name { get; set; }
    public Dictionary<string, Sub> Subs = new Dictionary<string, Sub>();
}

public class Sub
{
    public string Namex { get; set; }
    public string Namey { get; set; }
    public string Value { get; set; }
    public Dictionary<string, string> Paths { get; set; }
}

我的问题是:如何深入检查cont1和cont2的公平性?我的意思是说,每个成员的平等和价值甚至在Subs对象中都深处。

在C#中是否有针对此类情况的功能,或者我必须根据自己的对象结构编写一个自定义方法来检查是否相等;

第二个问题:如果我可以创建两个不同的产品副本,则可以消除均等问题。我的意思是说我们有一个包含所有成员和值的基本Container对象,然后创建Container的两个单独副本,即cont1和cont2,这两个副本更改cont1中的值不会更改cont2中的相同值。

注意1:此克隆方法不起作用:

cont2 = new Dictionary<string, Container>(cont1);

注意2:在其他答案中,大多数建议的方法都是基于一个一级的词典(使用循环或LINQ进行检查),而不是在对象中具有属性和词典对象(具有自己的属性)的情况。

蒂姆·施密特(Tim Schmelter)

是的,您必须编写一个自定义方法来根据自己的对象结构检查是否相等。我想提供一个自定义IEqualityComparer<Container>IEqualityComparer<Sub>喜欢这里(GetHashCode实现了基于):

public class ContainerCheck : IEqualityComparer<Container>
{
    private SubCheck subChecker = new SubCheck();
    public bool Equals(Container x, Container y)
    {
        if (ReferenceEquals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        if (x.IDx != y.IDx || x.IDy != y.IDy || x.Name != y.Name)
            return false;
        // check dictionary
        if (ReferenceEquals(x.Subs, y.Subs))
            return true;
        if (x.Subs == null || y.Subs == null || x.Subs.Count != y.Subs.Count)
            return false;
        foreach (var kv in x.Subs)
            if (!y.Subs.ContainsKey(kv.Key) || subChecker.Equals(y.Subs[kv.Key], kv.Value))
                return false;
        return true;

    }

    public int GetHashCode(Container obj)
    {
        unchecked // Overflow is fine, just wrap
        {
            int hash = 17;
            // Suitable nullity checks etc, of course :)
            hash = hash * 23 + obj.IDx.GetHashCode();
            hash = hash * 23 + obj.IDy.GetHashCode();
            hash = hash * 23 + obj.Name.GetHashCode();
            foreach (var kv in obj.Subs)
            {
                hash = hash * 23 + kv.Key.GetHashCode();
                hash = hash * 23 + subChecker.GetHashCode(kv.Value);
            }

            return hash;
        }
    }
}

public class SubCheck : IEqualityComparer<Sub>
{
    public bool Equals(Sub x, Sub y)
    {
        if (ReferenceEquals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        if (x.Namex != y.Namex || x.Namey != y.Namey || x.Value != y.Value)
            return false;
        // check dictionary
        if (ReferenceEquals(x.Paths, y.Paths))
            return true;
        if (x.Paths == null || y.Paths == null || x.Paths.Count != y.Paths.Count)
            return false;
        foreach(var kv in x.Paths)
            if (!y.Paths.ContainsKey(kv.Key) || y.Paths[kv.Key] != kv.Value)
                return false;
        return true;
    }

    public int GetHashCode(Sub obj)
    {
        unchecked // Overflow is fine, just wrap
        {
            int hash = 17;
            // Suitable nullity checks etc, of course :)
            hash = hash * 23 + obj.Namex.GetHashCode();
            hash = hash * 23 + obj.Namey.GetHashCode();
            hash = hash * 23 + obj.Value.GetHashCode();
            foreach (var kv in obj.Paths)
            {
                hash = hash * 23 + kv.Key.GetHashCode();
                hash = hash*23 + kv.Value.GetHashCode();
            }

            return hash;
        }
    }
} 

这应该深入检查所有属性和字典。然后,您可以使用以下循环将两个词典彼此进行比较:

bool equal = true;
var allKeys = cont1.Keys.Concat(cont2.Keys).ToList();
var containerChecker = new ContainerCheck();

foreach (string key in allKeys)
{
    Container c1;
    Container c2;
    if (!cont1.TryGetValue(key, out c1) || !cont2.TryGetValue(key, out c2))
    {
        equal = false;
    }
    else
    {
        // deep check both containers
        if (!containerChecker.Equals(c1, c2))
            equal = false;
    }
    if(!equal)
        break;  // or collect differences
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章