Introduction
Here's a simple technique for converting between signed and unsigned integer
arrays.
The problem
Suppose you have this unsigned array and you'd like to convert it to a signed
array.
uint[]
uia = { 1, 2, 3, 4 };
Let's try a simple cast first:
int[]
ia = (int[])uia; // doesn't compile!
This doesn't work because the C# compiler is very fussy. It knows that casting
uints to ints might cause a problem if the uints are larger than 2,147,483,647
(the maximum allowed for an int) and so disallows it.
So, you'd probably end up doing something like this:
int[]
ia = new int[uia.Length];
for (int i = 0;
i < ia.Length; i++) ia[i] = (int)uia[i];
Which works but is a bit long winded. So is there an easier way to do?
An easy solution
The answer is 'yes' - just cast it to object before you cast to the new array
type!
int[]
ia = (int[])(object)uia;
// works fine at
both compile time and runtime
Why does this work - does it involve boxing?
It works because, by casting to object first, we're postponing the conversion
decision until run time.
The CLR is not as fussy as the C# compiler and allows the conversion. If any
uint is bigger than Int32.MaxValue (not the case here) it's simply 'wrapped
around' to the corresponding negative int value.
As arrays are reference types anyway, there's no boxing here.
Where else does this technique work?
It also works when converting int[] to uint[] and when converting (in either
direction) between the other integral types:
byte[] and sbyte[]
ushort[] and short[]
ulong[] and long[]
Of course, you need to be careful when array elements are outside the range of
the conversion type (particularly with bytes) unless you're happy for the values
to be wrapped around.