c# - 在集合之间查找唯一对象
问题描述
我有一个测试,我创建了两个列表。一个代表我已经从某个来源(我无法控制)收集并收集的数据,另一个代表我的存储库中已经存在的已知数据。
它们看起来像这样:
var newAccounts = new[]
{
new Account
{
Id = 1,
SA_ID = 1,
SA_Name = "Sa_Name1",
RelationshipType = "new",
LE_ID = 1,
LE_GroupID = 1,
SiteID = 1,
MinDate = DateTime.Now.AddDays(-1),
MaxDate = DateTime.Now.AddDays(1),
DaysOn = 1,
Child1 = new List<Child1>{ new Child1
{
SiteID = 1,
MaxDate = DateTime.Today.AddDays(7),
MinDate = DateTime.Today.AddDays(1),
}
},
Child2 = new List<Child2>
{
new Child2
{
SA_ID = 1,
LastUpdate = DateTime.Now.AddDays(-1),
CommentText = "Account added",
Status = AccountStatus.AccountAdded.ToString(),
}
}
},
new Account
{
Id = 2,
SA_ID = 2,
SA_Name = "Sa_Name2",
RelationshipType = "new",
LE_ID = 2,
LE_GroupID = 2,
SiteID = 2,
MinDate = DateTime.Now.AddDays(-2),
MaxDate = DateTime.Now.AddDays(2),
DaysOn = 2,
},
new Account
{
Id = 3,
SA_ID = 3,
SA_Name = "Sa_Name3",
RelationshipType = "new",
LE_ID = 3,
LE_GroupID = 3,
SiteID = 3,
MinDate = DateTime.Now.AddDays(-3),
MaxDate = DateTime.Now.AddDays(3),
DaysOn = 3,
}
};
var knownAccounts = new[]
{
new Account
{
Id = 1,
SA_ID = 1,
SA_Name = "Sa_Name1",
RelationshipType = "new",
LE_ID = 1,
LE_GroupID = 1,
SiteID = 1,
MinDate = DateTime.Now.AddDays(-1),
MaxDate = DateTime.Now.AddDays(1),
DaysOn = 1,
Child1 = new List<Child1>{ new Child1
{
SiteID = 1,
MaxDate = DateTime.Today.AddDays(7),
MinDate = DateTime.Today.AddDays(1),
}
},
Child2 = new List<Child2>
{
new Child2
{
SA_ID = 1,
LastUpdate = DateTime.Now.AddDays(-1),
CommentText = "Account added",
Status = AccountStatus.AccountAdded.ToString(),
}
}
}
};
在我的单元测试中,我想从中删除Account ID 1
,newAccounts
所以我的收藏中只剩下 2 个条目。到目前为止,这些是我的尝试:
public List<T> ReturnUniqueEntriesList<T>(List<T> newAccounts, List<T> knownAccounts)
{
var a = knownAccounts.Intersect(newAccounts).ToList();
var listA = newAccounts.Except(knownAccounts).ToList();
var listB = knownAccounts.Except(newAccounts).ToList();
var result = listB.Intersect(listA).ToList();
return result;
}
当我运行它时,最终结果为 0。a
也返回 0 并且listA
&listB
简单地返回它们各自的对象。
我在这里做错了什么/错过了什么?任何帮助,将不胜感激
解决方案
覆盖 Account 的 Equals 和 GetHashcode,以便它们不依赖于默认实现(对象的内存地址)。这意味着 C# 将能够在执行例外时正确地将它们等同起来。
例如:
public class Account{
public override bool Equals(object other){
return other is Account a && a.Id == this.Id; //nb; is returns false if other is a null, even if it is an Account
}
public override int GetHashCode(){
return Id.GetHashCode();
}
}
实际上,以下两个帐户非常不同:
var a = new Account { Id = 1 };
var b = new Account { Id = 1 };
..因为他们住在不同的内存地址。
通过覆盖 Equals 以便它比较另一个的 Id,而不管其他属性,然后您基本上可以实现您似乎描述的“具有相同 ID 的两个帐户对象是等效的”的情况
如果其他属性因素影响到决策,也添加这些属性。Hashcode.Combine 是一种有用的方法,可以将多个哈希码组合起来,以解决获取多个属性的哈希码以产生合适的新信号哈希码的难题 - https://docs.microsoft.com/en-us/dotnet/api/system.hashcode。结合?view=net-5.0
推荐阅读
- json - 编组为 JSON 时带有反斜杠的额外双引号
- java - 迭代器可以用于哪些数据结构?
- microsoft-teams - 将文件附加到 Microsoft Teams 上的频道
- vue.js - 如何在 vue3 中实现 debounce
- linux - “源”命令的参数有什么作用?
- c - 为什么“for”循环不起作用并且程序停止?
- owasp - OWASP ZAP 中的“Out of Scope”和“Out of context:”是什么意思?
- python - 函数的输入张量必须来自 `tf.keras.Input`。已接收:0(缺少上一层元数据)并且找不到原因
- .net - 未能在资源“https://localhost:5001/_framework/System.Private.Xml.dll”的“完整性”属性中找到有效摘要
- elasticsearch - Elasticsearch:在映射中定义字段词汇