Когда система. Двойной не двойной?

Посмотрев какdouble.Nan == double.NaN всегда ложно в C #, мне стало любопытно, как было реализовано равенство под капотом. Поэтому я использовал Resharper для декомпиляции структуры Double, и вот что я нашел:

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

    public const double NaN = double.NaN;

    // more stuff removed...
}

Это, кажется, указывает на структуруDouble объявляет константу, которая определяется в терминах этого специального нижнего регистраdouble, хотя я'Я всегда думал, что оба были полностью синонимами. Какие'Более того, если я перейду к реализации в нижнем регистре, Resharper просто прокрутит меня до объявления в верхней части файла. Аналогично, переход к реализации строчныхNaN просто приводит меня к объявлению константы ранее в строке!

Так что я'Я пытаюсь понять это, казалось бы, рекурсивное определение. Это просто артефакт декомпилятора? Возможно ограничение в Resharper? Или этот строчный дубль на самом деле совсем другой зверь - представляющий что-то на более низком уровне от CLR / CTS?

Где жеNaN действительно пришел?

 Marc Gravell22 мая 2013 г., 16:12
@KonradRudolphglobal::System.Double, по крайней мере. Но ты можешь быть злым ...pastie.org/7943586
 David Heffernan22 мая 2013 г., 18:16
Скомпилированный код попросит устройство с плавающей запятой (8087, SSE и т. Д.) Выполнить сравнение. И FPU использует стандартные правила IEEE754.
 Nolonar22 мая 2013 г., 15:53
NaN средстваNot a Number и может быть положительным или отрицательным, так же, какInfinity, На случай, если кому-то интересно.
 Matthew Watson23 мая 2013 г., 00:31
@Virtlink Я не сделалголосовать за закрытие Почему вы думаете, что я сделал? Я предоставлял некоторые связанные ссылки, как я уже сказал.
 Matthew Watson23 мая 2013 г., 17:13
@Virtlink Да, я нея думаю, что это был дубликат; Я просто пытался предоставить некоторую дополнительную информацию.
 Lawrence22 мая 2013 г., 15:59
Обратите внимание, что double.Nan.GetHashCode () всегда имеет значение -524288, а double.Nan.Equals (double.Nan) всегда имеет значение true. Похоже, они просто непереопределить оператор ==, чтобы соответствовать другим понятиям равенства.
 Daniel A.A. Pelsmaeker22 мая 2013 г., 23:31
@MatthewWatson Хотя эти вопросы могут бытьсвязанные сЭто, безусловно, разные вопросы, и ни один из ответов не дает точного ответа на этот вопрос.Является ли вопрос точной копией ?:неттогда неголосовать за закрытие!
 Konrad Rudolph22 мая 2013 г., 16:06
И просто чтобы прояснить это:double являетсявсегда идентичныйSystem.Double, Первое является синонимом последнего.
 Daniel A.A. Pelsmaeker23 мая 2013 г., 16:49
@MatthewWatson Извините,дон»голосовать за закрытие был более направлен наширокая публика' который использовал ваши ссылки, чтобы пометить это какточный дубликат, которого нет.
 Joel Rondeau22 мая 2013 г., 15:47
Просто используя VS для просмотра шоу метаданныхpublic const double NaN = 0.0 / 0.0;
 Matthew Watson22 мая 2013 г., 15:47

Ответы на вопрос(2)

особенно если он для чего-то встроенного. Фактический IL здесь (для .NET 4.5, по крайней мере):

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

то есть это обрабатывается непосредственно в IL черезNaN маркер.

Тем не менее, потому что это (constliteral в ил) получитсясгорел в сайт вызова; где-нибудь еще, который используетdouble.NaN будуттакже использоватьfloat64(NaN), Аналогично, например, если я делаю:

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

оба эти заданиябудет выглядеть одинаково в финальном IL (они оба будутldc.i4.2).

Из-за этого большинство декомпиляторов распознают паттерн ILNaN и представить его на языке "с эквивалентомdouble.NaN, Но это неt означает, что сам код является рекурсивным; они, вероятно, просто нене иметь чек на "но разве это не двойник?, В конечном счете, это просто особый случай, когдаfloat64(NaN) является признанным значением в IL.

Кстати, отражатель декомпилирует это как:

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

Это снова неЭто означало, что это правда: просто то, что может иметь тот же конечный результат.

Решение Вопроса

лучшим источником, который вы можете получить для сборок .NET, является фактический исходный код, который использовался для их сборки. Точность превосходит любой декомпилятор, комментарии могут быть весьма полезными. СкачатьСправочный источник.

Вы'тогда увидим, чтоDouble.NaN ISN»т определено в IL, как предположил Марк, этона самом деле в файле исходного кода C #.net/clr/bcl/system/double.cs файл исходного кода показываетреальный объявление:

  public const double NaN = (double)0.0 / (double)0.0;

Который использует преимущества компилятора C #, вычисляющего константные выражения во время компиляции. Или, говоря проще, NaN определяется компилятором C ++, так какs язык, который использовался для написания компилятора C #;)

Ваш ответ на вопрос