# Quickly asked: Should I use unsigned integers (uint, uint8, ...) in C#?

08/07/2021

I will drop the basics about what an unsinged integer is. Let's just concentrate on the fact whether or not you should use it. The obvious case would be as `Count` property on your array-like structures or lists. That thing can't get smaller than zero. Let's have a look at a few things, shall we?

## Common Language Specification aka CLS

Let's start with the CLS. In the CLS there is no datatypes which present unsigned values. That means if you write a library in C# where those types exist, you will get big problem in certain languages in the .NET ecosystem. But honestly who cares about CLS-compliant when >90% is C# and you are sure it will only be consumed from C# code.

## Can an array have a negative length?

Well no... but technically yes. There are some reasons Array.Length is `int32`

• .NET 1 only allowed objects the size of 2GB thus `int32` was good enough
• Interop with other languages needs int anyway
• -1 as often used as a marker For example binary search returns -1 when a value wasn't found (good that -1 can't be an useful length)
• Wrap around behavior of uint is dangerous

By the way if you want to see an negative (valid) index C/C++ comes to the rescue with pointers 😄 `

``````int a[3] = { 1, 2, 3 };
int* p = &a[1];  // Make p point to the second element

std::cout << p[-1];  // Prints the first element of a, equal to *(p - 1)
std::cout << p[ 0];  // Prints the second element of a, equal to *p
std::cout << p[ 1];  // Prints the third element of a, equal to *(p + 1)
``````

## Wrap around behavior of uint

``````uint a = uint.MaxValue  + 1;
Console.Write("a is " + a); // a is 0
``````

What happens is basically any arithemtic behaves like a ring. Just imagine the following arithemtic operation:

``````uint a = 100u;
uint b = 100u;
uint c = a * b;
``````

What really happens is that:

``````uint a = 100u;
uint b = 100u;
uint c = (a * b) % 2^32; // Modulo 2^32
``````

Okay this brings big issues for example if you want to an access an array: `uint arrayIndex = 0; MyArray[arrayIndex - 1];` Now you would access `uint.MaxValue`. Most likely there is nothing but given the probability you will run into issues. This is how uint behaves in C/C++. And this is the base for the .NET Runtime. Microsoft was at least very nice and provided us the `checked` keyword to not fall into this issue.

## For Loops

Let's have a look at the following code-snippet:

``````for (unsigned int i = 9; i >= 0; i--)
{
Console.WriteLine("Hello World");
}
``````

How often do you think the loop will run? ... The answer is indefinitely. Why? Because of the wrap around. An `uint` can't get smaller than 0, therefore `i >= 0` is a tautology and therefore always true.

## Complex arithmetic

Just image you mix unsinged and signed in formula. Just have a look at this: Preserving rules in C. There can be tricky tricky pitfalls when mixing both.

# So should I never use it?

No. There are reasons to use an `uint` but it should not be because of readability. In most cases `int` is big enough and economically.

## Bit Shifting

In .NET signed and unsinged integer behave differently when it comes to bit-shifts. Signed integers doing arithemtic shifts:

And unsigned integers do logical shifts:

If you need logical bitshifts you would take uints.

## Interop

From personal experience I can say that a lot of stuff which is close to the hardware still uses uint. For example OpenCL or nVidia's CUDA. If you ever tried the same in JAVA it is a bit pain in the a** as Java has no unsinged data types.

# Conclusion

There are cases where an uint makes sense. But in your every day life you are safer with a signed integer.

Since .NET Core 2.0 the Type `ValueTask`. It seems that there is a lot of overlap between `Task` and `ValueTask`. So let's have a deeper look into `ValueTask`. Where should we use it and how should we use it properly? And also: where we should not use is.
Sometimes you have an `Id` of an object and want to delete the underlying thing from the database. But it doesn't make sense to load the whole object from the database to memory first. So how can we achieve this quickly?