1

I have two variables.

int x = 1;
uint y = 2;

The types must remain int and uint. Yet I can't perform basic arithmetic with them.

y += x;

Cannot implicitly convert type 'int' to 'uint'. An explicit conversion exists (are you missing a cast?)

So I have to do something like this everytime?

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

Coming from a C/C++/Java background, this confuses me.
Is there something I'm missing here?

Why is this behavior different from the other languages mentioned?
Are there better alternatives?

I assume this is a common trip-up to newcomers of the language.
No, I'm not relying on underflow.

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
  • 1
    To perform `y += x` a conversion from `int` to `uint` has to be performed. Because that conversion is lossy compiler requires you to perform it explicitly. – MarcinJuraszek Mar 31 '16 at 02:35

1 Answers1

2

There is no guarantee that an int will fit into an uint, that's why you get the compiler error.

If you really want to perform the operation (that is, if you know somehow that the numbers will fit), you can cast like you did or use Convert methods.

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

If you are unsure if the numbers will fit, you can just clamp them:

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

Also, in some cases you can use an unchecked context. This won't give you errors, but will overflow values larger than it's possible to fit.

At last, if you want to map between their range of possible values, use int.MaxValue as offset:

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

int w = someint();
uint z = Convert.ToUint32(w + int.MaxValue);
heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • I can't use int because it might be negative or cause underflow, but I can use another uint and case underflow anyway? They are System.Int32 and System.UInt32. Wouldn't that mean they are guaranteed to be the same size? – Trevor Hickey Mar 31 '16 at 02:34
  • They are the same size in bits, but they don't represent the same numeric values. You cannot represent -1 as Uint32, for example. But if all you want is _map_ between them, then you can apply a "shift" by adding or subtracting `int.MaxValue`, which spans half the representable range of either one. – heltonbiker Mar 31 '16 at 02:36