IEnumerable.Except()不排除

时间:2016-07-04 15:40:00

标签: c# linq

我有两个数组。第一个包含所有成员,第二个包含所有声明的成员。我试图只使用except来获取无人认领的成员,但结果数组包括所有成员(第一个数组的精确副本)。

var junior_handler_All = db2.junior_handler.Include(j => j.person).Include(j => j.status).ToArray();

var junior_handler_Claimed = db.junior_handler.Include(j => j.person).Include(j => j.status).ToArray();

var junior_handler_Unclaimed = junior_handler_All.Except(junior_handler_Claimed).ToArray();

我还尝试使用具有相同结果的where查询来获取无人认领的成员。

var junior_handler_Unclaimed = junior_handler_All.Where(i => !junior_handler_Claimed.Contains(i.Junior_Handler_ID.ToString()));

为什么其中任何一个都无法运作?

2 个答案:

答案 0 :(得分:2)

ExceptContains比较元素的方式是调用GetHashCode()并且 - 如果该哈希值相等 - 调用Equals来检查两个元素是否相等。

因此,如果您将此应用于没有自己的GetHashCode()Equals()实现的引用类型,则此比较会产生一个简单的引用相等检查。

您可能不想比较对象的引用,而是某种ID。所以你有两个选择:

您可以覆盖班级中的GetHashCode()Equals()

public class Person
{
    public int ID { get; set; }

    public override bool Equals(object o)
    {
        return ID == (o as Person)?.ID;
    }
    public override int GetHashCode()
    {
        return ID;
    }
}

或者像这样实现IEqualityComparer<Person>

public class Comparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return x.ID == y.ID; // or whatever defines your equality
    }
    public int GetHashCode(Person obj)
    {
        return obj.ID; // or whatever makes a good hash
    }
}

并向Except提供此比较器的实例:

var junior_handler_Unclaimed =
     junior_handler_All.Except(junior_handler_Claimed, new Comparer()).ToArray();

答案 1 :(得分:0)

您需要更新您的类以实现IEquatable和/或覆盖Equals和GetHashCode。

参考文献:

MSDN除外:

  

使用默认相等比较器生成两个序列的集合差异以比较值

MSDN关于默认的相等比较器:

  

Default属性检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer。否则,它返回一个EqualityComparer,它使用由T提供的Object.Equals和Object.GetHashCode的覆盖。