簡體   English   中英

等於方法的奇怪行為

[英]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那么您將獲得默認值,這是您注意到的兩個大問題:

  • 有時效率不高
  • 包裝浮點數的結構不會自動獲得浮點數相等行為。 更一般而言,包裝T的結構不會自動獲得T相等的行為。

我的假設是.NET對原始類型使用不同的Equals實現。 但這似乎不正確,因為float和struct類型都可以轉換為System.ValueType。

本段對我來說沒有任何意義,所以我可能誤會了您,或者您認為繼承完全不正確。 每種類型都可以覆蓋Equals 用戶代碼可以將任何非空值類型裝箱,這與事實有什么關系? 我看不到您的兩個句子之間的聯系,並且您相信其中一個句子的事實表明有人在這里有錯誤的信念。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM