2

I was reading How can one simplify network byte-order conversion from a BinaryReader? and the initial code in the question made me think about the capabilities of the explicit cast between UInt32 and Int32. My main concern is with values greater than Int32.MaxValue or less than 0.

These casts should be equivalent, but one works and the other causes an error:

public static void TestConverstion()
{
    // runs just fine, CastBack == aUInt
    UInt32 aUInt = UInt32.MaxValue; // 4294967295
    Int32 anInt = (Int32)aUInt; // -1
    UInt32 castBack = (UInt32)aUInt; // 4294967295

    // Build Error: Constant value '4294967295' cannot be converted to a 'int' (use 'unchecked' syntax to override) 
    UInt32 oneLineCastBack = (UInt32)(Int32)UInt32.MaxValue;
}

Why is one valid and not the other?

Where is the behavior of this cast documented? The best documentation I could find was Explicit Numeric Conversions Table (C# Reference), which acknowledges that there is an explicit cast, but warns that explicit casts "may cause loss of precision or result in throwing exceptions". Experimentation says that no exception is thrown, nor is precision lost.

UInt32 Structure suggests that since UInt32 is not part of the Common Language Specification that you should just use an Int64 and waste half the bits when you need to represent a value above Int32.MaxValue but below UInt32.MaxValue.

Community
  • 1
  • 1
Denise Skidmore
  • 2,286
  • 22
  • 51
  • Where's it documented? http://msdn.microsoft.com/en-us/library/2xf6xbyc.aspx , http://msdn.microsoft.com/en-us/library/aa288039.aspx . MSDN can answer pretty much any question about the basic stuff. – cHao Aug 01 '13 at 20:22
  • 1
    It is very clear that 1st one is a `variable` so compiler has no guess what could have happen where as 2nd one is `Constant` so compiler knows the range and complaint you as error. – Sriram Sakthivel Aug 01 '13 at 20:26
  • Is Convert.ToInt32(uint) the same operation as (Int32)(uint)? – Denise Skidmore Aug 01 '13 at 20:30
  • But why does the compiler complain at all if it is a valid runtime operation? – Denise Skidmore Aug 01 '13 at 20:31
  • Convert.ToInt32(uint) is a different operation from (Int32)(uint). The first throws an exception (rather expected) and the second seems to convert just fine based on the bit representation of the value. (This is the behavior in C++, but I rather expected an exception in C#). – Denise Skidmore Aug 01 '13 at 20:35
  • It is `unchecked` context wrap your code in `checked context` and try it will throw `OverflowException` – Sriram Sakthivel Aug 01 '13 at 20:39
  • `unchecked{Int32 uncheckedInt = Convert.ToInt32(UInt32.MaxValue);}` still throws an exception. ToInt32 documentation is not the explicit cast documentation. – Denise Skidmore Aug 01 '13 at 20:47
  • Even when the explicit cast is put in an `checked` block, it has a different message in the `OverflowException` than `ToInt32`. `System.OverflowException was unhandled Message=Arithmetic operation resulted in an overflow. Source=Examples` vs. `System.OverflowException was unhandled Message=Value was either too large or too small for an Int32. Source=mscorlib` – Denise Skidmore Aug 01 '13 at 20:49

1 Answers1

2

The way you have the code laid out, you are simply dealing with the compiler's ability to determine the potential outcome. Nothing really changes. As the error message suggests to you, you could do this and arrive at the exact same result:

unchecked { UInt32 oneLineCastBack = (UInt32)(Int32)UInt32.MaxValue; }

The only difference between the two examples you give is that the second one is a direct cast of the const value to Int32 which the compiler can immediately recognize as an error.

DonBoitnott
  • 10,787
  • 6
  • 49
  • 68
  • http://msdn.microsoft.com/en-us/library/a569z7k8(v=vs.71).aspx "If neither checked nor unchecked is used, a constant expression uses the default overflow checking at compile time, which is checked. Otherwise, if the expression is non-constant, the run-time overflow checking depends on other factors such as compiler options and environment configuration." - So the value becomes a non-constant after being assigned to a variable, the language that describes what happens next is vague. – Denise Skidmore Aug 01 '13 at 20:38
  • I'm with you there, it is vague. But rightly so, there's no statement about environment that makes sense, and compiler options? You could weed through the list, but...http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx – DonBoitnott Aug 01 '13 at 20:46
  • This might be the right compiler option: http://msdn.microsoft.com/en-us/library/8wtf2dfz.aspx It metions cases of truncation, but does not mention cases of different bit representation of the same number of bits. – Denise Skidmore Aug 01 '13 at 21:04