2013-08-01 5 views
1

Я читал How can one simplify network byte-order conversion from a BinaryReader?, и исходный код в вопросе заставлял меня думать о возможностях явного литья между UInt32 и Int32. Моя основная проблема заключается в значениях, превышающих Int32.MaxValue или менее 0.Литье UInt32 в Int32: результаты других компиляторов

Эти забросы должны быть эквивалентны, но один работает, а другой вызывает ошибку:

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; 
} 

Почему один действует, а не другой?

Где поведение этого литого документировано? Лучшая документация, которую я мог найти, это Explicit Numeric Conversions Table (C# Reference), в которой признается, что существует явный приведение, но предупреждает, что явные приведения "может привести к потере точности или привести к исключениям". Экспериментация говорит, что исключение не выбрасывается, и точность не теряется.

UInt32 Structure предполагает, что поскольку UInt32 не является частью Common Language Specification, что вы должны просто использовать Int64 и тратить половину битов, когда вам нужно представлять значение выше Int32.MaxValue но ниже UInt32.MaxValue.

+0

Где это задокументировано? http://msdn.microsoft.com/en-us/library/2xf6xbyc.aspx, http://msdn.microsoft.com/en-us/library/aa288039.aspx. MSDN может ответить практически на любой вопрос об основных вещах. – cHao

+1

Очень ясно, что 1-й является «переменным», поэтому компилятор не знает, что могло бы произойти там, где второй - «Константа», поэтому компилятор знает диапазон и жалуется на вас как на ошибку. –

+0

Is Convert.ToInt32 (uint) та же операция, что и (Int32) (uint)? –

ответ

1

Способ, которым вы располагаете кодом, вы просто имеете дело с способностью компилятора определять потенциальный результат. Ничего не меняется. Поскольку сообщение об ошибке говорит вам, вы могли бы сделать это и прийти к точно такому же результату:

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

Единственное различием между этими двумя примерами, которые вы даете является то, что вторым один является прямым броском из const значение Int32, которое компилятор может сразу распознать как ошибку.

+0

http://msdn.microsoft.com/en-us/library/a569z7k8(v=vs.71).aspx "Если ни проверенные, ни необработанные не используются, выражение константы использует проверку переполнения по умолчанию в время компиляции, которое проверено. В противном случае, если выражение не является постоянным, проверка переполнения во время выполнения зависит от других факторов, таких как параметры компилятора и конфигурация среды."- Таким образом, значение становится непостоянным после назначения переменной, язык, описывающий то, что происходит дальше, является неопределенным. –

+0

Я с вами там, это расплывчато. Но это справедливо, нет никаких утверждений о среде, которая делает смысл и параметры компилятора? Вы можете сорвать список, но ... http: //msdn.microsoft.com/en-us/library/19z1t1wy.aspx – DonBoitnott

+0

Это может быть правильный вариант компилятора: http: // msdn .microsoft.com/en-us/library/8wtf2dfz.aspx Он измеряет случаи усечения, но не упоминает случаи разного представления битов того же количества бит. –