You should almost always use Int32
or Int64
(and, no, you do not get credit by using UInt32
or UInt64
) when looping over an array or collection by index.
The most obvious reason that it's less efficient is that all array and collection indexes found in the BCL take Int32
s, so an implicit cast is always going to happen in code that tries to use Int16
s as an index.
The less-obvious reason (and the reason that arrays take Int32
as an index) is that the CIL specification says that all operation-stack values are either Int32
or Int64
. Every time you either load or store a value to any other integer type (Byte
, SByte
, UInt16
, Int16
, UInt32
, or UInt64
), there is an implicit conversion operation involved. Unsigned types have no penalty for loading, but for storing the value, this amounts to a truncation and a possible overflow check. For the signed types every load sign-extends, and every store sign-collapses (and has a possible overflow check).
The place that this is going to hurt you most is the loop itself, not the array accesses. For example take this innocent-looking loop:
for (short i = 0; i < 32000; i++) {
...
}
Looks good, right? Nope! You can basically ignore the initialization (short i = 0
) since it only happens once, but the comparison (i<32000
) and incrementing (i++
) parts happen 32000 times. Here's some pesudo-code for what this thing looks like at the machine level:
Int16 i = 0;
LOOP:
Int32 temp0 = Convert_I16_To_I32(i); // !!!
if (temp0 >= 32000) goto END;
...
Int32 temp1 = Convert_I16_To_I32(i); // !!!
Int32 temp2 = temp1 + 1;
i = Convert_I32_To_I16(temp2); // !!!
goto LOOP;
END:
There are 3 conversions in there that are run 32000 times. And they could have been completely avoided by just using an Int32
or Int64
.
Update: As I said in the comment, I have now, in fact written a blog post on this topic, .NET Integral Data Types And You
UInt32 does not allow for negative numbers. From MSDN:
The UInt32 value type represents unsigned integers with values ranging from 0 to 2 to the power of 32 or 2**32 (which equals to 4,294,967,295).
Best Answer
Functionally, there is no difference between the types
Integer
andSystem.Int32
. In VB.NETInteger
is just an alias for theSystem.Int32
type.The identifiers
Int32
andInteger
are not completely equal though.Integer
is always an alias forSystem.Int32
and is understood by the compiler.Int32
though is not special cased in the compiler and goes through normal name resolution like any other type. So it's possible forInt32
to bind to a different type in certain cases. This is very rare though; no one should be defining their ownInt32
type.Here is a concrete repro which demonstrates the difference.
In this case
local1
andlocal2
are actually different types, becauseInt32
binds to the user defined type overSystem.Int32
.