double
is a C# keyword - an alias for the type System.Double
. Your assumption is that mscorlib.dll
was written in C#. Also, the decompiler is wrong. The constant for NaN
is there as a definite double value - the decompiler just expects that you want to see that constant as double.NaN
rather than the value of double.NaN
(which you probably don't even know).
In the compiled IL (inside the dll), constants are not referenced by name. This is a very important thing. If you do eg.:
const int Zero = 0;
Console.Write(Zero);
The code (not the declaration) will compile the same as
Console.Write(0);
This is a very important point to understand, because constant values are resolved at compile-time, not run-time. If you take the constant from a referenced library, and the value of the constant changes in that referenced library, you'll be left with the old value in your code, until you recompile against the new verison.
If you need a "constant" that can change between library versions, you'd better use static properties instead, eg.:
static int Zero { get { return 0; } }
Then what's referenced is actually the property, not its value.
The same behaviour exists with default parameters in C#. They are also resolved at compile time, so they didn't quite make constructor/method overloads obsolete :)
Imagine a method:
public void DoSomething(bool isSafe = true);
All nice and good. But then you decide that the default behaviour should be unsafe, rather than safe. Or worse, you change the meaning of the boolean (this is a significant problem when you're using parameter names like flag
:) ). So you change the definition
public void DoSomething(bool isSafe = false);
Everyone who calls your method as DoSomething()
will call it with the old value of the parameter, true
. Until they recompile. This can be very frustrating and hard to debug if you don't understand when are default parameters resolved :)
Back to the alias keywords - there are situations, where the two aren't the same. However, this is because of the way the compiler parses certain expressions. The prime example is the enum
keyword:
enum MyEnum : byte {} // Valid, an enum with an underlying type of byte.
enum MyEnum2 : System.Byte {} // Invalid, unexpected token.
// "Type byte, sbyte, short, ushort, int, uint, long, or ulong expected"
And since we're already talking about enums, yes, those have the same problem. They are represented by their underlying "number". If you change that, the old number suddenly points to a different "enum value" and vice versa - again, a big problem if your creating or consuming some API :)