C# LINQ,但不删除匹配项
我有两个我自己的类的列表,我正试图把所有的项目都放在一个列表中,而不是另一个列表中C# LINQ,但不删除匹配项,c#,linq,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> inte
//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
我在Equals中的最后一个if语句上放置了一个断点,当我进入Except行时,它正确地命中了断点,我可以看到this.PropertyAddress.ToString()
在某些情况下等于y.PropertyAddress.ToString()
,所以它正在查找一些相等的对象,但似乎没有排除它们
知道怎么了吗
编辑:显示两个列表中都有匹配的地籍类型。
定义CompareField并使用与Equals方法相同的属性:
public override string CompareField => PropertyAddress.ToString();
您好,此代码可能会帮助您:
ComDataList = ComDataList.Intersect(ConsoleDataList).ToList();
或
您是否实现了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);
}
}
公共抽象类DataObjectBase
{
公共虚拟整数ID{get;set;}
//如果实体尚未保存,则为true:
public virtual bool IsTransient{get{return ID在使用join时,您正在使用CompareField检查它们之间的公共属性。但是,使用except是在比较整个对象。如果具有相同公共字段的两个对象也没有所有公共属性,这将不起作用。最好使用此ComDataList.except(intersectLose).ToList();这可能有助于@SubashKharel在本例中,CompareField
实际上与Equals-public override字符串CompareField=>PropertyAddress.ToString()相同
-但这无关紧要,因为我在连接中使用了比较字段来表示交叉松散
,而我在例外中没有实际使用比较字段。是的,您仅在连接对象列表时使用了PropertyAddress字段,但在使用Exception时比较了整个对象。使用。Exception
使用对象的等于方法-请参见above在我的问题中。我的Equals方法只检查PropertyAddress字段。如果PropertyAddress字段匹配,则两个CAPropertyType被视为相等。我已经实现了IEquatable接口,它只需要Equals(并且根本不使用GetHashCode函数-我之前已经实现了它,并且在调试中没有遇到它)重写Equals(Object)的类型也必须重写GetHashCode;否则,哈希表可能无法正常工作。请参阅:
intersectLoose = ComDataList.Intersect(ConsoleDataList).ToList();
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);
}
}