按特定值比较子列表到父列表

时间:2016-03-20 14:56:43

标签: c# .net-4.0

我有2个列表,首先是父对象的第二个子对象。子对象具有额外的属性,我想与父类的属性进行比较。

这是示例

  public class Parent
{
    public int X { get; set; }
}

public class Child : Parent
{
    public int Y { get; set; }
}

public class ClassXCompare : IEqualityComparer<Parent>
{
    public bool Equals(Parent x, Parent y)
    {
        var child = (Child)y;
        return x.X == child.Y;
    }

    public int GetHashCode(Parent parent)
    {
        int parentXhash = parent.X.GetHashCode();
        // Calculate the hash code for the product. 
        return parentXhash ;
    }
}

现在,如果我测试以下内容,它总是会失败

var parentList= new List<Parent>
        {
            new Parent {X = 5},
            new Parent {X = 6}
        };
        var childList= new List<Child>
        {
            new Child {Y = 5},
            new Child {Y = 6}
        };
        var compare = new ClassXCompare();
        var diff = parentList.Except(childList, compare);
        Assert.IsTrue(!diff.Any()); // Fail ???

我认为我的问题位于 GetHashCode 功能

知道如何解决这个问题吗?

  

(请忽略应用程序的设计,这是简化的   问题的版本)

2 个答案:

答案 0 :(得分:2)

这是一个真正可怕的设计。在比较器中转换为特定类型的需要将导致您不会遇到麻烦。

但是,下面的代码通过了。请注意不同的转换方法,空检查以及除外行上的列表顺序。

问题是Child实例没有设置X,并且Except方法将值传递给Equals的顺序意味着“x”是Child而不是“y”。

这可能会起作用,但你应该认真重新考虑你的设计。

public class Parent
{
    public int X { get; set; }
}

public class Child : Parent
{
    public int Y { get; set; }
}

public class ClassXCompare : IEqualityComparer<Parent>
{
    public bool Equals(Parent x, Parent y)
    {
        var child = y as Child;

        return child != null && x.X == child.Y;
    }

    public int GetHashCode(Parent parent)
    {
        var c = parent as Child;
        if (c == null)
            return parent.X.GetHashCode();
        else
            return c.Y.GetHashCode();
    }
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var parentList = new List<Parent>
            {
                    new Parent {X = 5},
                    new Parent {X = 6}
            };
        var childList = new List<Child>
            {
                    new Child {Y = 5},
                    new Child {Y = 6}
            };
        var compare = new ClassXCompare();
        var diff = childList.Except(parentList, compare);
        Assert.IsTrue(!diff.Any()); // Fail ???     
    }
}

答案 1 :(得分:0)

只有当GetHashCode为两个项返回相同的值时,才会调用Set / Dictionary中的Equals - 请参阅General advice and guidelines on how to properly override object.GetHashCode()。修复它的最简单方法是使用类似这样的东西,其中子值用于计算HashCode(如果可用):

public class ClassXCompare : IEqualityComparer<Parent>
{
    public bool Equals(Parent x, Parent y)
    {
        var child = (Child)y;
        return x.X == child.Y;
    }

    public int GetHashCode(Parent parent)
    {
        var child = parent as Child;
        return child == null ?
            parent.X : child.Y.
    }
}

如果你必须处理多个子类,它不是非常可扩展的。

不确定是否有一种简单的方法来处理多个子类,除了一些自定义generic IEqualityComparer之外,甚至只会缩短它。

PS 此外,我不确定第二个参数是否总是Child(怀疑该标准涵盖了它,尽管此特定用法中的当前实现似乎以适当的方式工作),所以你可能不得不使IEqualityComparer对参数的顺序更宽松。