實(shí)驗(yàn)代碼
Son s1 = new(), s2 = new();
Console.WriteLine("_ = s1 == s2");
_ = s1 == s2;
Console.WriteLine();
Console.WriteLine("_ = s1 != s2;");
_ = s1 != s2;
Console.WriteLine();
Console.WriteLine("_ = s1.Equals(s2);");
_ = s1.Equals(s2);
Console.WriteLine();
Console.WriteLine("_ = ((object)s1).Equals(s2);");
_ = ((object)s1).Equals(s2);
Console.WriteLine();
Console.WriteLine("s1 is IEquatable<Father>");
Console.WriteLine(s1 is IEquatable<Father>);
Console.WriteLine();
Console.WriteLine("s1.GetHashCode()");
Console.WriteLine(s1.GetHashCode());
Console.WriteLine();
public class Father : IEquatable<Father>
{
public virtual int A { get; set; }
public virtual int B { get; set; }
public override bool Equals(object? obj)
{
Console.WriteLine("object Equals");
if (obj is not null and Father)
{
Father f = (Father)obj;
return f.A == A && f.B == B;
}
return false;
}
public override int GetHashCode()
{
Console.WriteLine("GetHashCode");
return 0;
}
public static bool operator ==(Father left, Father right)
{
Console.WriteLine("比較==");
return left.Equals(right);
}
public static bool operator !=(Father left, Father right)
{
Console.WriteLine("比較!=");
return !(left == right);
}
public bool Equals(Father? other)
{
Console.WriteLine("IEquatable Equals");
return ((object)this).Equals(other);
}
}
public class Son : Father
{
public override int A { get => base.A; set => base.A = value; }
}
運(yùn)行結(jié)果
_ = s1 == s2
比較==
IEquatable Equals
object Equals
_ = s1 != s2;
比較!=
比較==
IEquatable Equals
object Equals
_ = s1.Equals(s2);
IEquatable Equals
object Equals
_ = ((object)s1).Equals(s2);
object Equals
s1 is IEquatable<Father>
True
s1.GetHashCode()
GetHashCode
0
在父類(lèi)重寫(xiě)的 Equals 方法,繼承的 IEquatable 接口,重寫(xiě)的 == ,!= 運(yùn)算符,重寫(xiě)的 GetHashCode 方法在子類(lèi)中仍然是表現(xiàn)為被重寫(xiě)的狀態(tài)。
子類(lèi)實(shí)現(xiàn) IEquatable 接口
現(xiàn)在讓子類(lèi)也實(shí)現(xiàn) IEquatable 接口
Son s1 = new(), s2 = new();
s1.Equals(s2);
public class Father : IEquatable<Father>
{
public virtual int A { get; set; }
public virtual int B { get; set; }
public override bool Equals(object? obj)
{
Console.WriteLine("object Equals");
if (obj is not null and Father)
{
Father f = (Father)obj;
return f.A == A && f.B == B;
}
return false;
}
public override int GetHashCode()
{
Console.WriteLine("GetHashCode");
return 0;
}
public static bool operator ==(Father left, Father right)
{
Console.WriteLine("比較==");
return left.Equals(right);
}
public static bool operator !=(Father left, Father right)
{
Console.WriteLine("比較!=");
return !(left == right);
}
public bool Equals(Father? other)
{
Console.WriteLine("IEquatable Equals");
return ((object)this).Equals(other);
}
}
public class Son : Father, IEquatable<Son>
{
public bool Equals(Son? other)
{
Console.WriteLine("IEquatable<Son>.Equals");
return ((object)this).Equals(other);
}
}
運(yùn)行結(jié)果
IEquatable<Son>.Equals
object Equals
Equals 方法的重載
此時(shí)代碼提示如下
子類(lèi)實(shí)現(xiàn)接口后,調(diào)用的默認(rèn)就是子類(lèi)實(shí)現(xiàn)的 Equals 方法。也可以用強(qiáng)制轉(zhuǎn)換調(diào)用父類(lèi)的 Equals 方法
這里屬于 Equals 方法的不同類(lèi)型的重載。通過(guò) public override bool Equals(object? obj)
重寫(xiě)的 Equals 方法也是一種重載。這個(gè)重載是每一個(gè) object 的子類(lèi)都有的,不重寫(xiě)這個(gè)方法時(shí)比較的是兩個(gè)對(duì)象的引用是否相等。
所有判斷相等性的運(yùn)算符、方法必須一起重寫(xiě)
上面那些判斷相等性的方法、運(yùn)算符必須要么一起重寫(xiě),要么全部不重寫(xiě)。實(shí)現(xiàn)了 IEquatable 接口后也要重寫(xiě)全部。如果不全部重寫(xiě),這些不同的相等性判斷方法返回結(jié)果不一致會(huì)造成混亂。
對(duì)象放到哈希表的過(guò)程
對(duì)象在放到哈希表里首先是計(jì)算哈希值,然后嘗試放到哈希表中的對(duì)應(yīng)位置。如果該位置已經(jīng)有一個(gè)對(duì)象了,再調(diào)用 Equals 方法判斷是不是同一個(gè)對(duì)象,如果是,就不再放一次了。如果不是,則說(shuō)明發(fā)生了哈希沖突,此時(shí)會(huì)將新對(duì)象用鏈表掛在哈希表該位置。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-603905.html
重寫(xiě) Equals 方法后,如果將對(duì)象放在哈希表里,必須重寫(xiě) GetHashCode 方法
重寫(xiě)相等性判斷方法時(shí),如果想讓對(duì)象能夠在哈希表里正常工作,必須也重寫(xiě) GetHashCode 方法。GetHashCode 方法原本是根據(jù)引用值生成哈希碼,原本的相等性運(yùn)算也是根據(jù)引用值。這種情況可以正常工作。但是,如果重寫(xiě)了 Equals 方法,不重寫(xiě) GetHashCode 方法,會(huì)導(dǎo)致明明相等的兩個(gè)對(duì)象返回的哈希值不同(因?yàn)樗麄兊囊貌煌谑枪1碇械膬蓚€(gè)位置儲(chǔ)存了兩個(gè)相等的對(duì)象。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-603905.html
重寫(xiě) GetHashCode 的注意事項(xiàng)
- 不要使用會(huì)變化的字段生成哈希碼。因?yàn)樽侄巫兓?,生成的哈希碼不同,此時(shí)再調(diào)用 GetHashCode 方法得到的哈希碼不同,這會(huì)導(dǎo)致字段變化后無(wú)法在哈希表中找到該對(duì)象了。
- 兩個(gè)對(duì)象使用 Equals 方法判斷相等性返回 true 時(shí),GetHashCode 方法必須能夠返回相同的值。否則會(huì)導(dǎo)致兩個(gè)相等的對(duì)象具有不同的哈希值,這會(huì)導(dǎo)致哈希表中有重復(fù)的元素。
到了這里,關(guān)于C# 父類(lèi)實(shí)現(xiàn)的 IEquatable<T> 接口,重寫(xiě)的相等性判斷函數(shù)都能被子類(lèi)繼承的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!