Почему я не могу вычесть int из uint?

У меня есть две переменные.

int x = 1;
uint y = 2;

Типы должны оставаться int и uint. Тем не менее, я не могу выполнять элементарные арифметические действия с ними.

y += x;

Невозможно неявно преобразовать тип «int» в «uint». Существует явное преобразование (вам не хватает приведения?)

То есть я должен делать что-то подобное каждый раз?

if (x < 0)
{
    y -= (uint)Math.Abs(x);
}
else
{
    y += (uint)x;
}

Меня это смущает из-за опыта работы с C/C++/Java.
Есть ли что-то, что я здесь упускаю?

Почему это поведение отличается от других упомянутых языков?
Есть ли лучшие альтернативы?

Я предполагаю, что это обычная ошибка для новичков в языке.
Нет, я не полагаюсь на недополнение.


person Trevor Hickey    schedule 31.03.2016    source источник
comment
Для выполнения y += x необходимо выполнить преобразование из int в uint. Поскольку это преобразование с потерями, компилятор требует, чтобы вы выполнили его явно.   -  person MarcinJuraszek    schedule 31.03.2016


Ответы (1)


Нет никакой гарантии, что int поместится в uint, поэтому вы получаете ошибку компилятора.

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

if (x < 0)
{
    y -= Convert.ToUint32(Math.Abs(x));
}
else
{
    y += Convert.ToUint32(x);
}

Если вы не уверены, подойдут ли числа, вы можете просто зажать их:

uint result = Math.Max(uint.MinValue(Math.Min(uint.MaxValue, x))

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

Наконец, если вы хотите сопоставить их диапазон возможных значений, используйте int.MaxValue в качестве смещения:

uint x = someuint();
int y = Convert.ToInt32(x - int.MaxValue);

int w = someint();
uint z = Convert.ToUint32(w + int.MaxValue);
person heltonbiker    schedule 31.03.2016
comment
Я не могу использовать int, потому что он может быть отрицательным или вызвать потерю памяти, но я все равно могу использовать другой uint и случай потери памяти? Это System.Int32 и System.UInt32. Разве это не означает, что они гарантированно будут одного размера? - person Trevor Hickey; 31.03.2016
comment
Они имеют одинаковый размер в битах, но не представляют одни и те же числовые значения. Например, вы не можете представить -1 как Uint32. Но если все, что вам нужно, это сопоставить между ними, то вы можете применить сдвиг, добавив или вычтя int.MaxValue, что охватывает половину представляемого диапазона любого из них. - person heltonbiker; 31.03.2016