LINQ Distinct不按预期工作

3

我有一个简单的类如下所示:

public class Person : IEquatable<Person>
{
    public bool Equals(Person other) 
    {
        return Name.Equals(other.Name, StringComparison.InvariantCultureIgnoreCase);
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }

    public Person(string name)
    {
        Name = name;
    }
    public string Name { get; set; }
}

现在我正在创建一个人员数组,对其进行去重,并使用默认的相等比较器进行传递,这个比较器是由 IEquatable<Person> 实现的。

var persons = new[] {new Person("foo"), new Person("Foo"), new Person("bar"), new Person("Bar")};
persons.Distinct(EqualityComparer<Person>.Default);

当我检查不同的人时,我期望得到一个包含“foo,bar”的IEnumerable<Person>。然而,内容是“foo,Foo,bar,Bar”。
当我使用“foo,foo,bar,bar”初始化列表时,结果符合预期。因此,我认为在Person.Equals方法中的StringComparison.InvariantCultureIgnoreCase被忽略了。
有人有想法吗?

一些其他的注释(你的问题已经被答案解决了)。你应该考虑在Equals中检查other是否为null。由于Person可能是从中派生的(它不是一个sealed类),还要考虑说if (GetType() != other.GetType()) { return false; }。请注意,你的对象是可变的(Name可以在对象构造后更改),而可变对象不应在字典或哈希集合中被修改。通过说return obj as Person;来覆盖虚拟的Object.Equals(object obj)方法。 - Jeppe Stig Nielsen
2个回答

3

目前需要使 GetHashCode() 方法返回不区分大小写的哈希码,在此情况下,对于大写和小写字母不同的 Name,将生成不同的哈希码。

例如:

public override int GetHashCode() 
{ 
    return Name.ToUpperInvariant().GetHashCode(); 
} 

1
使用 ToUpperInvariant()ToLower() 更高效。 - myermian
谢谢,我只是依靠记忆在做,我知道肯定有更好的方法。 - DaveShaw

2

GetHashCode()方法会为应被视为相同的对象返回不同的哈希码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接