Подтвердить что ты не робот

Разница двух "uint"

Когда вы пытаетесь объявить неподписанную переменную в С#.NET со значением вне своего диапазона значений, она помечена как ошибка компилятора, но если вы производите отрицательное значение во время выполнения и назначаете его этой переменной во время выполнения, значение обертывает.

uint z = -1; // Will not compile

uint a = 5;
uint b = 6;
uint c = a - b; // Will result in uint.MaxValue

Есть ли веская причина, почему переменные без знака обертываются в такой ситуации, а не бросают исключение?

Спасибо.

4b9b3361

Ответ 1

Объявление неназначенной переменной в С# не помечено ошибкой - попытка присвоить недопустимое значение переменной. Например, здесь переменная, которая определенно не назначена (предполагается, что она локальна) после объявления:

uint z;

-1 не является допустимым значением для uint не более 0,5, поэтому ваш пример не будет компилироваться.

Теперь, как и для остальных: целые числа просто переносятся на переполнение - так же, как добавление от 1 до int.MaxValue возвращает int.MinValue. Это значительное улучшение производительности за счет того, что программа проверяет каждую операцию для переполнения - ценой потенциально не обнаруженной ошибки.

Это, только если вы находитесь в неконтролируемом контексте, заметьте - если вы выполняете какую-либо из этих операций в проверенном контексте, вместо этого вы получите исключение. Например,

class Test
{
    static void Main()
    {
        checked
        {
            uint a = 5;
            uint b = 6;
            uint c = a - b;
        }
    }
}

Запустите это, и вы увидите, как OverflowException получит бросок. Если это то, что вы хотите для всего проекта, вы можете установить его в свойствах проекта (или скомпилировать с параметром командной строки /checked+ до csc.)

EDIT: Стоит отметить, что другие ответы показали, что вы можете поместить меньшее количество кода в проверенный контекст - просто объявление и назначение c или даже просто расчет. Все это довольно гибко.

Ответ 2

Обертка связана с тем, что dfault С# не установлен. Если вы добавите "проверенный" блок, будет обнаружено переполнение:

    uint a = 3, b = 4;
    checked
    {
       uint c = a - b; // throws an overflow
    }

Что касается компилятора: он просто требует действительных данных.

Ответ 3

Это только значение по умолчанию - вы можете изменить параметры компиляции, чтобы активировать проверку переполнения времени выполнения. Если вы включите это, исключения будут выбрасываться так, как вы ожидаете. В качестве альтернативы вы можете включить проверку конкретной операции, поместив ее в выделенный блок.

uint c = checked(a - b);

Ответ 4

Возможно, стоит пояснить здесь, что uint - это unsigned int, а не неназначенный int. Большая разница!

Ответ 5

Всегда используйте double. Разница в производительности незначительна, и она более гибкая и удобная. Эта практика предотвращает исключения и сокращает время разработки. Анальные люди ненавидят это, хотя.

Ответ 6

Причина, по которой он переносится на отрицательный, состоит из Two Complement, который используется для целочисленной арифметики.

Короткий ответ заключается в том, что в качестве знака используется самый старший бит. Нуль положителен; один отрицательный.