I looked under the hood of List<T>
and came across the following piece of code:
public T this[int index] {
get {
// Following trick can reduce the range check by one
if ((uint) index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
return _items[index];
}
set {
if ((uint) index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
_items[index] = value;
_version++;
}
}
In both if
statements, index
and _size
(of type Int32
) are casted to UInt32
, I know it is not because of overflow, because first .if
has a comment stating otherwise
Question: What is this concept of casting integer to unsigned-integers other than overflow, and in what specific situation can it be useful to a developer?
The point is to handle both negative numbers and positive numbers in one step.
If you cast a negative numbers to uint
, the result is guaranteed to be larger than than int.MaxValue
. So any negative index will fail the (uint) index >= (uint)_size
check. If you remove the cast you would need to do two checks: index < 0 || index >= _size
. Since the cast is "free" this end up improving performance a bit.
Note that this will not work in a checked context