IEqualityComparer上的奇怪行为
本文关键字:IEqualityComparer | 更新日期: 2023-09-27 18:31:55
我正在尝试为我的对象实现一个IEqualityComparer,它基本上可以检测一个对象是否比另一个对象旧。以下更简单的示例将综合我想要完成的任务:
class Program
{
static void Main(string[] args)
{
var authorsList = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=20 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=14 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Trevor", Lastname = "Smith", Age=15 },
new Author{ Firstname = "Brian", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Billy", Lastname = "Smith", Age=11 },
};
var authorsListExcept = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
};
var authorsList2 = authorsList
.Except(authorsListExcept, new AuthorUpdatedComparer()).ToList();
}
}
class Author
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Age { get; set; }
}
class AuthorUpdatedComparer : IEqualityComparer<Author>
{
public bool Equals(Author x, Author y)
{
return x.Age >= y.Age;
}
public int GetHashCode(Author obj)
{
//Check whether the object is null
if (Object.ReferenceEquals(obj, null)) return 0;
int FirstnameHash = (obj.Firstname ?? "").GetHashCode();
int LastnameHash = (obj.Lastname ?? "").GetHashCode();
int finalResult = FirstnameHash ^ LastnameHash;
return finalResult;
}
}
我的作者列表2结果将是:鲍勃·史密斯,20岁* 14岁的Bom Smith特雷弗·史密斯,15岁* 布莱恩·史密斯,11岁* 11岁的比利·史密斯
但取而代之的是不包括 14 岁的鲍勃史密斯。在调试时,我得出的结论是,包括 20 岁的鲍勃史密斯之后的比较器开始使用它有一个比较器,然后排除了鲍勃的年龄小于 20 岁。
在我看来,这是一种奇怪的行为,它应该只排除那些更年轻或与作者列表上的人年龄相同的人ListExcept。我试图阅读msdn文档,我想要它应该发生什么:字体: http://msdn.microsoft.com/en-US/图书馆/BB336390(v=vs.100).aspx
有人可以帮助我吗?谢谢雨果·萨尔加多
以下 LINQ 查询提供所需的结果:
var result =
authorsList.GroupBy(x => Tuple.Create(x.Firstname, x.Lastname))
.SelectMany(g => g.Where(x => authorsListExcept.All(e => e.Firstname != x.Firstname || e.Lastname != x.Lastname || e.Age < x.Age)));
以下查询也会生成此结果。它应该表现得更好:
var result =
authorsList.GroupBy(x => Tuple.Create(x.Firstname, x.Lastname))
.GroupJoin(authorsListExcept, x => x.Key,
x => Tuple.Create(x.Firstname, x.Lastname),
(a, e) => a.Where(x => x.Age > e.Select(z => z.Age)
.DefaultIfEmpty(0)
.Max()))
.SelectMany(x => x)
第三个选项(与上一个相同,但在查询语法上):
var result =
(from a in authorsList
group a by Tuple.Create(a.Firstname, a.Lastname) into g
join e in authorsListExcept on g.Key equals Tuple.Create(e.Firstname, e.Lastname) into er
from age in er.Select(x => x.Age).DefaultIfEmpty()
select g.Where(x => x.Age > age)).SelectMany(x => x);
接口IEqualityComparer<T>
用于检查相等性。它与任何排序无关。因此,您不能以尝试的方式使用它。
通常:此接口的实现应始终在GetHashCode
实现和Equals
方法中使用完全相同的属性集。
如果我了解了您想要什么,请尝试此操作。
class Program
{
static void Main(string[] args)
{
var authorsList = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=20 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=14 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Trevor", Lastname = "Smith", Age=15 },
new Author{ Firstname = "Brian", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Billy", Lastname = "Smith", Age=11 },
};
var authorsListExcept = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
};
var authorsList2 = authorsList.Where(x => !authorsListExcept.Any(y => y.Firstname == x.Firstname && y.Lastname == x.Lastname && x.Age <= y.Age));
}
}
public class Author
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Age { get; set; }
}