I think this question will bring me instant fame here on Stack Overflow.
Suppose you have the following type:
// represents a decimal number with at most two decimal places after the period struct NumberFixedPoint2 { decimal number; // an integer has no fractional part; can convert to this type public static implicit operator NumberFixedPoint2(int integer) { return new NumberFixedPoint2 { number = integer }; } // this type is a decimal number; can convert to System.Decimal public static implicit operator decimal(NumberFixedPoint2 nfp2) { return nfp2.number; } /* will add more nice members later */ }
It was written so that only safe conversions are allowed that do not lose accuracy. However, when I try this code:
static void Main() { decimal bad = 2.718281828m; NumberFixedPoint2 badNfp2 = (NumberFixedPoint2)bad; Console.WriteLine(badNfp2); }
I am surprised that this compiles and, when it starts, writes out 2 . It is important here to convert the int value (value 2 ) to NumberFixedPoint2 . (Overloading WriteLine , which takes the value a System.Decimal , is preferred if someone is wondering.)
Why is conversion from decimal to NumberFixedPoint2 allowed on Earth? (By the way, in the above code, if NumberFixedPoint2 changes from structure to class, nothing changes.)
Did you know that the C # language specification says that implicit conversion from int to user type implies the existence of a “direct” explicit conversion from decimal to this user type?
It gets a lot worse. Try using this code instead:
static void Main() { decimal? moreBad = 7.3890560989m; NumberFixedPoint2? moreBadNfp2 = (NumberFixedPoint2?)moreBad; Console.WriteLine(moreBadNfp2.Value); }
As you can see, we have (raised) Nullable<> conversions. But oh yes, it compiles.
When compiling on the x86 platform , this code produces an unpredictable numerical value. Which one changes from time to time. For example, I once received 2289956 Now this is a serious mistake!
When compiling for the x64 platform, the above code crashes the application with a System.InvalidProgramException with the message Common Language Runtime found an invalid program. . According to the documentation, the InvalidProgramException class:
This usually indicates an error in the compiler that generated the program.
Does anyone (like Eric Lippert or someone who worked with canceled conversions in the C # compiler) know the cause of these errors? How, what is a sufficient condition that we do not encounter them in our code? Since the type NumberFixedPoint2 is actually what we have in real code (we manage other people's money, etc.).