[英]Strange behavior of Equals method
根據這個答案https://stackoverflow.com/a/8315745/5324847.Net應該通過反射或按位比較值類型。 但是,如果我們看一下這段代碼,就會發現兩者都不是(或者兩者都可以??)。
//Bitwise test
//if .Net compares bitwise then last line should be false
//if it uses reflections then last line should be true
float a = -0.0f;
float b = 0.0f;
Console.WriteLine(string.Join("",BitConverter.GetBytes(a))); //prints 000128
Console.WriteLine(string.Join("",BitConverter.GetBytes(b))); //prints 0000
Console.WriteLine(a == b); //True
Console.WriteLine(a.Equals(b)); //prints True
//Reflection test
//if .Net compares using reflection then last line should be false
//if it uses bitwise comparsion then last line should be true
a = float.NaN;
b = float.NaN;
Console.WriteLine(string.Join("",BitConverter.GetBytes(a))); //prints 00192255
Console.WriteLine(string.Join("",BitConverter.GetBytes(b))); //prints 00192255
Console.WriteLine(a == b); //False
Console.WriteLine(a.Equals(b)); //prints True
如果我們將變量包裝在結構中,.Net將使用按位比較。 證明:
public struct FloatS
{
public float x;
}
public static void Main()
{
//bitwise test
//if .Net compares bitwise then last line should be false
//if it uses reflections then last line should be true
FloatS a = new FloatS();
FloatS b = new FloatS();
a.x = -0.0f;
b.x = 0.0f;
Console.WriteLine(string.Join("",BitConverter.GetBytes(a.x))); //prints 000128
Console.WriteLine(string.Join("",BitConverter.GetBytes(b.x))); //prints 0000
Console.WriteLine(a.x == b.x); //True
Console.WriteLine(a.Equals(b)); //prints False -- this time corectly because it's bitwise comparsion
//Reflection test
//if .Net compares using reflection then last line should be false
//if it uses bitwise comparsion then last line should be true
a.x = float.NaN;
b.x = float.NaN;
Console.WriteLine(string.Join("",BitConverter.GetBytes(a.x))); //prints 00192255
Console.WriteLine(string.Join("",BitConverter.GetBytes(b.x))); //prints 00192255
Console.WriteLine(a.x == b.x); //False
Console.WriteLine(a.Equals(b)); //prints True - also corectly
}
我的假設是,.Net對基本類型使用Equals的不同實現。 但這似乎是不正確的,因為float和struct類型都可以轉換為System.ValueType 。
有人可以解釋發生了什么嗎?
根據...,。NET應該通過反射或按位比較值類型。
您誤解了有關用戶定義的值類型的答案。
對於==
,僅針對浮點數使用特殊指令比較浮點數。 零和負零相等,NaN不等於任何東西,依此類推。
任何類型都可以覆蓋Equals
,而System.Single
可以這樣做。 x.Equals(y)
的語義為(x == y) || (IsNaN(x) && IsNaN(y))
(x == y) || (IsNaN(x) && IsNaN(y))
。 我不確定為什么為什么使Equals
和==
具有不同的行為,盡管可能是要確保float上的Equals
是等效關系,這對於某些應用程序(例如將floats放入哈希表中)是必需的。 (更新:我的假設是正確的;請參閱下面的評論。)
如果您編寫了一個用戶定義的值類型而沒有提供自己的Equals
那么您將獲得默認值,這是您注意到的兩個大問題:
我的假設是.NET對原始類型使用不同的Equals實現。 但這似乎不正確,因為float和struct類型都可以轉換為System.ValueType。
本段對我來說沒有任何意義,所以我可能誤會了您,或者您認為繼承完全不正確。 每種類型都可以覆蓋Equals
。 用戶代碼可以將任何非空值類型裝箱,這與事實有什么關系? 我看不到您的兩個句子之間的聯系,並且您相信其中一個句子的事實表明有人在這里有錯誤的信念。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.