根据这个答案 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。
有人可以解释发生了什么吗?
答案 0 :(得分:4)
根据...... .NET应该通过反射或按位来比较值类型。
您误解了该答案,即用户定义的值类型。
对于==
,使用浮动的特殊指令比较浮点数。零和负零相等,NaN等于零,甚至不等,等等。
任何类型都可以覆盖Equals
,System.Single
可以覆盖x.Equals(y)
。浮点数上的(x == y) || (IsNaN(x) && IsNaN(y))
具有Equals
的语义。我不确定为什么==
和Equals
有不同的行为,但可能确保浮点数上的Equals
是等价关系,这对于某些应用程序是必需的例如将浮动放入哈希表。 (更新:我的假设是正确的;请参阅下面的评论。)
如果您编写了用户定义的值类型而没有提供自己的Equals
,那么您将获得默认值,正如您所说,它有两个大问题:
我的假设是.NET对原始类型使用不同的Equals实现。但这似乎是不正确的,因为float和struct类型都可以转换为System.ValueType。
这一段对我来说没有任何意义,所以要么我误解了你,要么你相信继承的完全错误。每种类型都可以覆盖#include <iostream>
#include <string>
#include <utility>
template<typename OneType>
void foo_(OneType&& one)
{
std::cout << one;
}
template<typename... ArgTypes>
void foo(ArgTypes&&... arguments)
{
(foo_(std::forward<ArgTypes>(arguments)), ...);
}
int main()
{
foo(42, 43., "Hello", std::string("Bla"));
}
。这与用户代码可以包装任何非可空值类型的事实有什么关系?我没有看到你的两个句子之间的联系,而且你认为有一个句子的事实表明某人在这里有错误的信念。