何时System.Double不是double?

13

在C#中看到double.Nan == double.NaN总是false后,我对其背后的等式实现方式产生了好奇。因此,我使用Resharper去反编译Double结构体,这是我发现的:

public struct Double : IComparable, IFormattable, IConvertible, IComparable<double>, IEquatable<double>
{
    // stuff removed...

    public const double NaN = double.NaN;

    // more stuff removed...
}

这似乎表明结构体Double声明了一个常量,该常量是以特殊的小写double定义的,尽管我一直认为这两个是完全同义的。此外,如果我在小写的double上使用“转到实现”,Resharper仅仅会将我滚动到文件顶部的声明处。类似地,跳转到小写NaN的实现只会把我带到先前行中的常量声明处!

因此,我正在尝试理解这个看似递归的定义。这只是反编译器的产物吗?可能是Resharper的限制吗?还是说这个小写的double实际上是一种完全不同的东西 - 代表着CLR / CTS中更低层次的某些内容?

NaN真正来自哪里?


2
这与此相关吗?https://dev59.com/vm445IYBdhLWcg3wq8BY 以及 https://dev59.com/sGQo5IYBdhLWcg3wXeX5 - Matthew Watson
3
仅仅使用VS查看元数据会显示public const double NaN = 0.0 / 0.0; - Joel Rondeau
1
NaN 表示 不是数字,可以是正数或负数,就像 Infinity 一样。以防有人想知道。 - Nolonar
1
请注意,double.Nan.GetHashCode()始终为-524288,而double.Nan.Equals(double.Nan)始终为true。看起来他们只是没有覆盖“==”运算符以匹配其他相等的概念。 - Lawrence
1
@MatthewWatson 虽然这些问题可能是相关的,但它们肯定是不同的问题,而且没有一个答案完全回答了这个问题。这个问题是一个精确的重复吗?不是,那么就不要投票关闭! - Daniel A.A. Pelsmaeker
显示剩余6条评论
2个回答

15

要注意查看反编译代码,特别是对于内置内容。这里的实际IL(至少对于.NET 4.5而言)是:

.field public static literal float64 NaN = float64(NaN)
{
    .custom instance void __DynamicallyInvokableAttribute::.ctor()
}

即,这是通过 NaN 标记在 IL 中直接处理的。

然而,由于它是一个 const(在 IL 中是 literal),它将被“烧入”调用站点;任何其他使用 double.NaN 的地方也将同时使用 float64(NaN)。同样的例子,如果我执行以下操作:

const int I = 2;
int i = I;
int j = 2;

这两个赋值语句在最终的IL代码中看起来完全相同(它们都是ldc.i4.2)。

因此,大多数反编译器会识别IL模式NaN并用语言等效的double.NaN表示它。但这并不意味着代码本身是递归的;它们可能只是没有检查“但它是否是double.NaN本身?”。最终,这只是一个特殊情况,其中float64(NaN)是IL中一个被识别的值。

顺便说一下,反射器将其反编译为:

[__DynamicallyInvokable]
public const double NaN = (double) 1.0 / (double) 0.0;

这并不意味着这是真理 :p 只是这可能会导致相同的结果。


8
到目前为止,你可以得到的最好的.NET程序集来源就是实际用于构建它们的源代码。与任何反编译工具相比,它更准确,注释也可能非常有用。下载参考源代码
然后你还会看到,Double.NaN并不像Marc认为的那样在IL中被定义,它实际上在一个C#源文件中。 net/clr/bcl/system/double.cs源代码文件显示了真正的声明:
  public const double NaN = (double)0.0 / (double)0.0;

这利用了C#编译器在编译时评估常量表达式的特性。或者说,半开玩笑地说,NaN是由C++编译器定义的,因为这是用于编写C#编译器的语言;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接