比较引用类型对象的集合是不是相等,忽略集合中项目的顺序
Posted
技术标签:
【中文标题】比较引用类型对象的集合是不是相等,忽略集合中项目的顺序【英文标题】:Comparing a collection of reference type objects for equality ignoring order of items in collection比较引用类型对象的集合是否相等,忽略集合中项目的顺序 【发布时间】:2022-01-04 02:43:49 【问题描述】:我有以下示例类
public class Item
public string name get; set;
public double price get; set;
public class Basket
public Item[] items;
然后我创建了两个Basket
实例,都包含Item
s
var basket1 = new Basket()
items = new Item[]
new Item() name = "bread", price = 1.5 ,
new Item() name = "butter", price = 2
;
var basket2 = new Basket()
items = new Item[]
new Item() name = "butter", price = 2 ,
new Item() name = "bread", price = 1.5
;
我想比较 Basket1
和 Basket2
,忽略篮子中项目的顺序。比较时,此示例应返回 True
(它们相等)。我应该如何进行?
【问题讨论】:
这能回答你的问题吗? Is there any way to compare two lists in C# 如果顺序无关紧要,请使用HashSet<T>
。
【参考方案1】:
@Neil 的答案是正确的,只是它不适用于引用类型(字符串是一个例外,因为它们是不可变的)。
Item
是一个类,所以它是一个引用类型。
Except
使用默认的相等比较器来比较元素。由于 Item 是一个类,它会通过引用进行比较,这不是我们想要的解决方案。所以我们需要绕过默认比较,使用自定义相等比较器。为此目的存在Except
的重载。
您需要创建一个实现IEqualityComparer<Item>
的类型并将该类型的实例传递给Except
。
请参阅:Except overload documentation 和 IEqualityComparer documentation
这是一个可以在 Linqpad 中运行的示例。它同时使用Except
重载。一个返回false
,另一个返回true
:
void Main()
var basket1 = new Basket()
items = new Item[]
new Item() name = "bread", price = 1.5 ,
new Item() name = "butter", price = 2
;
var basket2 = new Basket()
items = new Item[]
new Item() name = "butter", price = 2 ,
new Item() name = "bread", price = 1.5
;
var isIdenticalByReference = (!(basket1.items.Except(basket2.items).Any())); // false
isIdenticalByReference.Dump();
var isIdenticalWithCustomEqualityComparer = (!(basket1.items.Except(basket2.items, new ItemEqualityComparer()).Any())); // true
isIdenticalWithCustomEqualityComparer.Dump();
// You can define other methods, fields, classes and namespaces here
public class Item
public string name get; set;
public double price get; set;
public int GetHashCode(object obj)
return (name?.GetHashCode() ?? 0) ^ price.GetHashCode();
public class ItemEqualityComparer : IEqualityComparer<Item>
public bool Equals(Item I1, Item I2)
if (I2 == null && I1 == null)
return true;
else if (I1 == null || I2 == null)
return false;
else return I1.name == I2.name && I1.price == I2.price;
public int GetHashCode(Item item)
return (item.name?.GetHashCode() ?? 0) ^ item.price.GetHashCode();
public class Basket
public Item[] items;
【讨论】:
【参考方案2】:你可以使用Except
,然后检查返回值是否有:
// first list
var list1 = new List<string>();
list1.Add("A");
list1.Add("B");
list1.Add("C");
list1.Add("D");
// second list
var list2 = new List<string>();
list2.Add("C");
list2.Add("D");
var list3 = list1.Except(list2);
var listIsIdentical = !list3.Any();
【讨论】:
抱歉列表必须包含引用类型 Object【参考方案3】:您需要覆盖从基类 Object 继承的默认 Equals 和 GetHashCode 方法。然后你就可以用!basket1.items.Except(basket2.items).Any();
正确比较两个篮子了。
【讨论】:
以上是关于比较引用类型对象的集合是不是相等,忽略集合中项目的顺序的主要内容,如果未能解决你的问题,请参考以下文章