LINQ除了不删除匹配

时间:2018-01-10 06:35:12

标签: c# linq

我有两个属于我自己班级的列表,我正在尝试将所有项目放在一个不在另一个中的项目中。

//List<CADataType> ConsoleDataList is a list of 1071 CADataTypes
//List<CADataType> ComDataList is a list of 2153 CADataTypes

//This list ends up containing 1144 items
List<CADataType> intersectLoose = (from console in ConsoleDataList
                                           join com in ComDataList 
                                           on console.CompareField equals com.CompareField
                                           select console).ToList();
//Therefore there are 1144 items that are in both lists

//This SHOULD result in 2153 - 1144 = 1009 items
List<CADataType> remove = ComDataList.Except(ConsoleDataList).ToList(); //<-- Problem is here
//Ends up containing 2153 items

CADataType实际上是一个抽象类,所有列表实际上都有CAPropertyData。这是CAPropertyData的Equals类:

public override bool Equals(CADataType obj)
{
    if (!(obj is CAPropertyData))
        return false;

    CAPropertyData y = (CAPropertyData)obj;

    if (this.PropertyAddress.ToString() == y.PropertyAddress.ToString()) //Breakpoint here
        return true;
    return false;
}

我在Equals中的最后一个if语句上放了一个断点,当我进入Except行时它正确地命中断点,我可以看到this.PropertyAddress.ToString()等于y.PropertyAddress.ToString() in在某些情况下,所以它找到了一些相同的对象,但它似乎并没有排除它们?

知道什么是错的吗?

编辑: intersectLoose可以向您显示两个列表中都有匹配的CADataType。 CompareField是使用与Equals方法相同的属性定义的:

public override string CompareField => PropertyAddress.ToString();

2 个答案:

答案 0 :(得分:0)

您好这段代码可以帮助您:

ComDataList = ComDataList.Intersect(ConsoleDataList).ToList();

intersectLoose = ComDataList.Intersect(ConsoleDataList).ToList();

答案 1 :(得分:0)

您是否已实施GetHashCode()Equals()GetHashCode()应始终一起实施。

请注意,生成的哈希码在计算后不应更改(例如,它应基于对象的ID),否则您将在以后遇到问题。

例如,我经常使用这个基类:

public abstract class DataObjectBase 
{
   public virtual int ID { get; set; }
   // true if the entity is not saved yet:
   public virtual bool IsTransient { get { return ID <= 0; } }

   // alternatively, if ID is string:
   // public virtual string ID { get; set; }
   // public virtual bool IsTransient { get { return string.IsNullOrEmpty(ID); } }

    public override bool Equals(object obj)
    {
        var other = obj as DataObjectBase;
        if (other == null)
            return false;
        else if (IsTransient ^ other.IsTransient)
            return false;
        else if (IsTransient && other.IsTransient)
            return ReferenceEquals(this, other);
        else if (this.GetType() != other.GetType())
            return false;
        else return ID == other.ID;
    }

    private int? cachedHashCode; // this is used because hashcode shouldn't change
    public override int GetHashCode()
    {
        if (cachedHashCode.HasValue) return cachedHashCode.Value;
        cachedHashCode = IsTransient ? base.GetHashCode() : ID.GetHashCode();
        return cachedHashCode.Value;
    }

    public static bool operator ==(DataObjectBase x, DataObjectBase y)
    {
        return Object.Equals(x, y);
    }

    public static bool operator !=(DataObjectBase x, DataObjectBase y)
    {
        return !(x == y);
    }
}