When disassembling code (with .NET Reflector version 5.1.3.0, for at least the C# language) that references System.Double.NaN or System.Single.NaN fields in the special case where the values are boxed as objects, the generated code is wrong because it is equivalent to System.Double.PositiveInfinity or System.Single.PositiveInfinity, respectively. This can easily be verified, since one can assert during runtime that "float.NaN != float.PositiveInfinity" and "double.NaN != double.PositiveInfinity", although this won't be the case for the disassembled code.
The following code is provided as an example that illustrates the problem.
Original...
using System;
using System.Diagnostics;
public class Program
{
public static object GetDoubleBoxed(int id)
{
switch (id)
{
case -1:
return double.NegativeInfinity; // Disassembles okay
case 1:
return double.PositiveInfinity; // Disassembles okay
}
return double.NaN; // Disassembles WRONG!!!
}
public static double GetDoubleValue(int id) // Disassembles exactly
{
switch (id)
{
case -1:
return double.NegativeInfinity;
case 1:
return double.PositiveInfinity;
}
return double.NaN;
}
public static object GetSingleBoxed(int id)
{
switch (id)
{
case -1:
return float.NegativeInfinity; // Disassembles okay
case 1:
return float.PositiveInfinity; // Disassembles okay
}
return float.NaN; // Disassembles WRONG!!!
}
public static float GetSingleValue(int id) // Disassembles exactly
{
switch (id)
{
case -1:
return float.NegativeInfinity;
case 1:
return float.PositiveInfinity;
}
return float.NaN;
}
public static void Main()
{
float valueSingleNaN = float.NaN; // Disassembles exactly
object boxedSingleNaN = float.NaN; // Disassembles WRONG!!!
float valueSingleInf = float.PositiveInfinity; // Disassembles exactly
object boxedSingleInf = float.PositiveInfinity; // Disassembles okay
Trace.Assert(valueSingleNaN != valueSingleInf); // Disassembles exactly
Trace.Assert(valueSingleInf == ((float)1.0 / (float)0.0)); // Disassembles okay
Trace.Assert(((float)boxedSingleNaN) != ((float)boxedSingleInf)); // Disassembles exactly, but would FAIL at runtime for recompiled disassembly!!!
Trace.Assert(((float)boxedSingleInf) == ((float)1.0 / (float)0.0)); // Disassembles okay
double valueDoubleNaN = double.NaN; // Disassembles exactly
object boxedDoubleNaN = double.NaN; // Disassembles WRONG!!!
double valueDoubleInf = double.PositiveInfinity; // Disassembles exactly
object boxedDoubleInf = double.PositiveInfinity; // Disassembles okay
Trace.Assert(valueDoubleNaN != valueDoubleInf); // Disassembles exactly
Trace.Assert(valueDoubleInf == ((double)1.0 / (double)0.0)); // Disassembles okay
Trace.Assert(((double)boxedDoubleNaN) != ((double)boxedDoubleInf)); // Disassembles exactly, but would FAIL at runtime for recompiled disassembly!!!
Trace.Assert(((double)boxedDoubleInf) == ((double)1.0 / (double)0.0)); // Disassembles okay
}
}
Generated...
using System;
using System.Diagnostics;
public class Program
{
public static object GetDoubleBoxed(int id)
{
switch (id)
{
case -1:
return (double)-1.0 / (double)0.0;
case 1:
return (double)1.0 / (double)0.0;
}
return (double)1.0 / (double)0.0;
}
public static double GetDoubleValue(int id)
{
switch (id)
{
case -1:
return double.NegativeInfinity;
case 1:
return double.PositiveInfinity;
}
return double.NaN;
}
public static object GetSingleBoxed(int id)
{
switch (id)
{
case -1:
return (float)-1.0 / (float)0.0;
case 1:
return (float)1.0 / (float)0.0;
}
return (float)1.0 / (float)0.0;
}
public static float GetSingleValue(int id)
{
switch (id)
{
case -1:
return float.NegativeInfinity;
case 1:
return float.PositiveInfinity;
}
return float.NaN;
}
public static void Main()
{
float valueSingleNaN = float.NaN;
object boxedSingleNaN = (float)1.0 / (float)0.0;
float valueSingleInf = float.PositiveInfinity;
object boxedSingleInf = (float)1.0 / (float)0.0;
Trace.Assert(valueSingleNaN != valueSingleInf);
Trace.Assert(valueSingleInf == float.PositiveInfinity);
Trace.Assert(((float)boxedSingleNaN) != ((float)boxedSingleInf));
Trace.Assert(((float)boxedSingleInf) == float.PositiveInfinity);
double valueDoubleNaN = double.NaN;
object boxedDoubleNaN = (double)1.0 / (double)0.0;
double valueDoubleInf = double.PositiveInfinity;
object boxedDoubleInf = (double)1.0 / (double)0.0;
Trace.Assert(valueDoubleNaN != valueDoubleInf);
Trace.Assert(valueDoubleInf == double.PositiveInfinity);
Trace.Assert(((double)boxedDoubleNaN) != ((double)boxedDoubleInf));
Trace.Assert(((double)boxedDoubleInf) == double.PositiveInfinity);
}
}
The following code is provided as an example that illustrates the problem.
Original...
Generated...