比较两个自定义对象(使用 IEqualityComparer)
首先,我会说我想要比较以下内容:我的自定义对象(项目)有一个字符串taxids
列表。我想查看一个列表中的所有字符串是否都出现在另一个字符串列表中(也将是另一个对象(项目)的另一个taxids
)。
所以,这就是类:
public class Item
{
public long taxid { get; set; }
public long contentid { get; set; }
public string taxname { get; set; }
public IEnumerable<string> taxids { get; set; }
}
然后这些是虚拟自定义对象:
List<string> numbers = new List<string> { "5", "1" };
List<string> numbers2 = new List<string> { "1", "2", "5","3","564" };
Item pr = new Item();
pr.contentid = 2517;
pr.taxid = 2246;
pr.taxids = numbers.AsEnumerable();
pr.taxname = "nameItem1";
List<Item> te = new List<Item>();
te.Add(pr);
IQueryable<Item> er = te.AsQueryable();
Item pr2 = new Item();
pr2.contentid = 0;
pr2.taxid = 0;
pr2.taxids = numbers2.AsEnumerable();
pr2.taxname = "nameItem2";
List<Item> te2 = new List<Item>();
te2.Add(pr2);
IQueryable<Item> er2 = te2.AsQueryable();
IQueryable<Item> both = er.Intersect(er2, new ItemComparer());
这里我使用自定义比较器ItemComparer
。这是其代码:
public class ItemComparer : IEqualityComparer<Item>
{
// items are equal if their names and item numbers are equal.
public bool Equals(Item x, Item y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the items' properties are equal.
return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Item item)
{
//Check whether the object is null
if (Object.ReferenceEquals(item, null)) return 0;
//Get hash code for the Name field if it is not null.
int hashItemName = item.taxids == null ? 0 : item.taxids.GetHashCode();
//Calculate the hash code for the item.
return item.taxids.GetHashCode();
//return "a".GetHashCode();
}
}
问题是变量both
在taxids字段中没有任何内容,通常我应该有一个列表。 “5”“1”
我知道 。比较时 hashCode 必须相同,但 taxids
永远不会相同。
有人可以进一步帮助我解决这个问题吗
? "a".GetHashCode()
=> 之类的所有内容始终返回相同的哈希码,这是否可行?
如果我对
Firstly, I will say what I want to compare the following: My Custom Object (Item) has a List of strings taxids
. I want to look if all the strings in one List occur in another list of strings (will be also another taxids
of another Object (Item).
So, this is the class:
public class Item
{
public long taxid { get; set; }
public long contentid { get; set; }
public string taxname { get; set; }
public IEnumerable<string> taxids { get; set; }
}
Then these are the dummy custom objects:
List<string> numbers = new List<string> { "5", "1" };
List<string> numbers2 = new List<string> { "1", "2", "5","3","564" };
Item pr = new Item();
pr.contentid = 2517;
pr.taxid = 2246;
pr.taxids = numbers.AsEnumerable();
pr.taxname = "nameItem1";
List<Item> te = new List<Item>();
te.Add(pr);
IQueryable<Item> er = te.AsQueryable();
Item pr2 = new Item();
pr2.contentid = 0;
pr2.taxid = 0;
pr2.taxids = numbers2.AsEnumerable();
pr2.taxname = "nameItem2";
List<Item> te2 = new List<Item>();
te2.Add(pr2);
IQueryable<Item> er2 = te2.AsQueryable();
IQueryable<Item> both = er.Intersect(er2, new ItemComparer());
Here I use a custom comparer ItemComparer
. Here is the code for this:
public class ItemComparer : IEqualityComparer<Item>
{
// items are equal if their names and item numbers are equal.
public bool Equals(Item x, Item y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the items' properties are equal.
return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Item item)
{
//Check whether the object is null
if (Object.ReferenceEquals(item, null)) return 0;
//Get hash code for the Name field if it is not null.
int hashItemName = item.taxids == null ? 0 : item.taxids.GetHashCode();
//Calculate the hash code for the item.
return item.taxids.GetHashCode();
//return "a".GetHashCode();
}
}
The problem is that variable both
has nothing in the taxids field, normally I should have a list of "5" "1".
I know that the hashCode must be the same when comparing. but taxids
will be never the same. Because we look for strings in another list of strings.
Anybody can further help me with this problem?
(Also a small question: If I return always the same hashcode for everything like "a".GetHashCode()
=> should this work or not?
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你的问题是你没有双向平等。 pr 和 pr 2 不相等,具体取决于对象的哪一侧。
我不确定您的比较器中是否能保证哪个对象是 x,哪个对象是 y。如果比较器中的
pr2
最终为x
怎么办?关于哈希码,您正在执行
taxids.GetHashCode()
- 这只是一个列表,而不是名称,不会告诉您任何有关相等性的信息。I think your problem is that you do not have bidirectional equality. depending on which side your object is, pr and pr 2 are not equal.
I am uncertain whether there is a guarantee which object is x and which is y in your comparer. What if
pr2
ends up to bex
in your comparer?with regard to the hash code, you are doing
taxids.GetHashCode()
- that is just a list and not a name and won't tell you anything about equality.您的相等比较当前不考虑集合中元素的不同顺序。作为一个粗略的解决方法,您可以在比较之前对它们进行排序,或者更好地将项目添加到哈希集中:
此外,您还必须提供
GetHashCode()
的适当实现,默认实现不依赖于实际项目在列表中,因此对于集合中具有相同元素的两个不同Item
实例,不会产生相同的哈希码。可以在 这篇其他 SO 帖子<中找到更适合您的情况的实现/a>.Your equality comparison does currently not take into account the different order of elements in the collections. As a crude workaround you could order them before comparing, or better add the items to a hashset:
Also you have to provide an appropriate implementation of
GetHashCode()
, the default implementation is not dependent on the actual items in the list, so wouldn't result in the same hashcode for two differentItem
instances that have the same elements in the collection. A more appropriate implementation for your case can be found in this other SO post.