gpt4 book ai didi

c# - 为什么在 Hashset 或其他集合中使用继承对象时 Equals(object) 胜过 Equals(T)?

转载 作者:IT王子 更新时间:2023-10-29 04:38:53 25 4
gpt4 key购买 nike

我知道我总是必须重写 Equals(object)GetHashCode()实现时 IEquatable<T>.Equals(T) .

但是,我不明白,为什么在某些情况下 Equals(object)胜过通用Equals(T) .

例如,为什么会发生以下情况?如果我声明 IEquatable<T>为接口(interface)实现具体类型 X对于它,将军Equals(object)Hashset<X> 调用在将这些类型的项目相互比较时。在所有其他情况下,至少有一侧被转换为界面,正确的 Equals(T)被称为。

这里有一个代码示例来演示:

public interface IPerson : IEquatable<IPerson> { }

//Simple example implementation of Equals (returns always true)
class Person : IPerson
{
public bool Equals(IPerson other)
{
return true;
}

public override bool Equals(object obj)
{
return true;
}

public override int GetHashCode()
{
return 0;
}
}

private static void doEqualityCompares()
{
var t1 = new Person();

var hst = new HashSet<Person>();
var hsi = new HashSet<IPerson>();

hst.Add(t1);
hsi.Add(t1);

//Direct comparison
t1.Equals(t1); //IEquatable<T>.Equals(T)

hst.Contains(t1); //Equals(object) --> why? both sides inherit of IPerson...
hst.Contains((IPerson)t1); //IEquatable<T>.Equals(T)

hsi.Contains(t1); //IEquatable<T>.Equals(T)
hsi.Contains((IPerson)t1); //IEquatable<T>.Equals(T)
}

最佳答案

HashSet<T>电话 EqualityComparer<T>.Default在没有提供比较器时获取默认的相等比较器。

EqualityComparer<T>.Default确定是否 T工具 IEquatable<T> .如果是,它使用那个,如果不是,它使用 object.Equalsobject.GetHashCode .

你的 Person对象实现 IEquatable<IPerson>不是IEquatable<Person> .

当你有一个 HashSet<Person>它最终检查是否 Person是一个 IEquatable<Person> ,它不是,所以它使用 object方法。

当你有一个 HashSet<IPerson>它检查是否 IPerson是一个 IEquatable<IPerson> ,确实如此,所以它使用了这些方法。


至于剩下的情况,为什么会这样:

hst.Contains((IPerson)t1);

调用 IEquatable Equals方法,即使它调用了 HashSet<Person> .你在这里打电话 ContainsHashSet<Person> 上并传入 IPerson . HashSet<Person>.Contains要求参数为 Person ;一个IPerson不是一个有效的论点。但是,HashSet<Person>也是一个 IEnumerable<Person> , 自 IEnumerable<T>是协变的,这意味着它可以被视为 IEnumerable<IPerson> , 它有一个 Contains接受 IPerson 的扩展方法(通过 LINQ)作为参数。

IEnumerable.Contains还使用 EqualityComparer<T>.Default在未提供时获取其相等比较器。在这个方法调用的情况下,我们实际上调用了 ContainsIEnumerable<IPerson> 上, 这意味着 EqualityComparer<IPerson>.Default正在检查是否 IPerson是一个 IEquatable<IPerson> ,它是,所以 Equals方法被调用。

关于c# - 为什么在 Hashset 或其他集合中使用继承对象时 Equals(object) 胜过 Equals(T)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28434991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com