From the comments:
Just to be on the safe side, because I noticed the Count is a int but not a uint
TL;DR:
When the List<T> class was designed, Microsoft's .NET class library design rules meant that UInt32 (aka uint) could not be used for any public members, so instead Int32 (aka int) was used.
Longer answer:
- The reason why Countis anint(akaInt32) property instead of auint(orUInt32) property is because theList<T>type was defined when the Common Language Specification (the "CLS") was still being respected by Microsoft.
- Ostensibly, redistributable and reusable libraries should only use CLS-approved data-types and should avoid using non-CLS-compliant data-types.
- Int32is CLS-compliant.
- UInt32is not CLS-compliant.
 
- The CLS exists because (at the time, around 2000-2005) Microsoft had this grand design for using .NET/CLR as the runtime and underlying type-system for many radically different programming languages - not just C# and VB.NET, but also Java (yup), OCaml-style functional languages like F#, and even JavaScript, Python, and PHP.
- ...and many of those languages simply don't support unsigned integer types; in-fact, high-profile languages like Java still don't support unsigned types.
- ...so in order to accommodate languages used by masochists, like Java, the main .NET class library had to be designed with restrictions on the possible data-types they could use, which means they have to use signed integers to represent unsigned values.
- Therefore, if Countwas typed asUInt32instead ofInt32then users of those other languages couldn't useList<T>.Countat all.
 
- Since .NET Core was released, I don't believe there has been any official deprecation of the Common Language Specification, but even if Microsoft hasn't officially abandoned it, the rest of the .NET ecosystem seems to have.
Can List<T>.Count ever be negative or otherwise invalid?
Provided you use a List<T> instance in a safe manner, then no, the .Count property will always return a value in the range 0 to 2^31 (the actual maximum count of a List<T> is a different question which is already answered here).
However, if you use a List<T> in a thread-unsafe manner (such as having 2 or more threads concurrently adding and removing items from a list without using lock correctly), or if you use tricks like reflection to override the .Count property's field value then yes, you can break things. So don't do that :)
Common Language Specification (CLS)
The motivation for the CLS is described in this article:
- To enable full interoperability scenarios, all objects that are created in code must rely on some commonality in the languages that are consuming them (are their callers).
- Since there are numerous different languages, .NET has specified those commonalities in something called the Common Language Specification (CLS).
The Common Language Specification is described in this MSDN article, which has a list of types built-in to .NET but which are verboten for use in CLS-compliant frameworks and redistributable libraries.
- System.SByteaka- sbyte.- 
- Signed octet value.
- This is the only signed, as opposed to unsigned, type prohibited by the CLS.
- Curiously, Java actually has a signed byte type.
 
- System.UInt16aka- ushort.
- System.UInt32aka- uint.
- System.UInt64aka- ulong.
- System.UIntPtr.
Also:
- The rules for CLS compliance apply only to a component's public interface, not to its private implementation.
- For example, unsigned integers other than Byteare not CLS-compliant [...].