Why do C# containers and GUI classes use int and not uint for size related members?
I would imagine that Microsoft chose Int32
because UInt32
is not CLS-compliant (in other words not all languages that use the .NET framework support unsigned integers).
using uint vs int
Your observation of why uint
isn't used in the BCL is the main reason, I suspect.
UInt32 is not CLS Compliant, which means that it is wholly inappropriate for use in public APIs. If you're going to be using uint in your private API, this will mean doing conversions to other types - and it's typically easier and safer to just keep the type the same.
I also suspect that this is not as common in C# development, even when C# is the only language being used, primarily because it is not common in the BCL. Developers, in general, try to (thankfully) mimic the style of the framework on which they are building - in C#'s case, this means trying to make your APIs, public and internal, look as much like the .NET Framework BCL as possible. This would mean using uint sparingly.
Why is C# DateTime Seconds property type int and not uint?
Using int
as the default data type tend to make programming easier, since it is large enough for most common use cases, and limits the risk someone makes a mistake with unsigned arithmetic. It will often have much greater range than actually needed, but that is fine, memory is cheap, and cpus may be optimized for accessing 32-bit chunks of data.
If you wanted the most precise datatype a byte
would be most appropriate, but what would you gain from using that instead of an int? There might be a point if you have millions of values, but that would be rare to store something like seconds in that way.
As mentioned in the comments, unsigned types are not CLS compliant, so will limit compatibility with other languages that do not support unsigned types. And this would be needed for a type like DateTime.
You should also prefer to use specific types over primitives. For example using TimeSpan to represent, well, a span of time.
Why is List T .Count a signed int? Can List T .Count ever be negative?
From the comments:
Just to be on the safe side, because I noticed the Count is a
int
but not auint
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
Count
is 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.
Int32
is CLS-compliant.UInt32
is 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
Count
was typed asUInt32
instead ofInt32
then users of those other languages couldn't useList<T>.Count
at all.
- Ostensibly, redistributable and reusable libraries should only use CLS-approved data-types and should avoid using non-CLS-compliant data-types.
- 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.
- So I think we can finally stop using CA1014.
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.SByte
akasbyte
.- 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.UInt16
akaushort
.System.UInt32
akauint
.System.UInt64
akaulong
.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
Byte
are not CLS-compliant [...].
Is numbers comparisons as uint faster than normal int in c#
The linked Dictionary source contains this comment;
// Should be a while loop https://github.com/dotnet/runtime/issues/9422
// Test in if to drop range check for following array access
if ((uint)i >= (uint)entries.Length)
{
goto ReturnNotFound;
}
entry = ref entries[i];
The uint
comparison here isn't faster, but it helps speed up the array access. The linked github issue talks about a limitation in the runtime compiler, and how this loop structure allows further optimisations. Since this uint
comparison has been performed explicitly, the compiler can prove that 0 <= i < entries.Length
. This allows the compiler to leave out the array boundary test and throw of IndexOutOfRangeException
that would otherwise be required.
In other words, at the time this code was written, and performance profiling was performed. The compiler wasn't smart enough to make simpler, more readable code, run as fast as possible. So someone with a deep understanding of the limitations of the compiler tweaked the code to make it better.
Why do functions take an int as an argument when its value logically can not be 0
I had a similar question ages ago, although more for my own interfaces, not the core ones.
The short answer (given by no other than Eric Lippert, and repeated in answers to other questions) is: The Common Language Specification rules state that you should not use uint
in public interfaces because not all languages that are designed to work with .NET actually have such a type. Java derivatives like J# come to mind – Java only has signed integral types.
Why is Array.Length an int, and not an uint
Unsigned int isn't CLS compliant and would therefore restrict usage of the property to those languages that do implement a UInt
.
See here:
Framework 1.1
Introduction to the .NET Framework Class Library
Framework 2.0
.NET Framework Class Library Overview
Why does .NET Framework not use unsigned data types?
Unsigned numeric types are not CLS compliant so they should not be used for any API - especially the .NET framework.
Basically, CLS compliant code only utilizes types that are available in all .NET languages. Some languages (like VB.NET) does not support unsigned numeric types.
Related Topics
ASP.NET MVC 5 Group of Radio Buttons
How to Run a Winform from Console Application
Best Way to Remove Duplicate Entries from a Data Table
How to Get Every Nth Item from a List<T>
Requested Registry Access Is Not Allowed
Getting a Url with an Url-Encoded Slash
Blazor - Display Wait or Spinner on API Call
Regular Expression Groups in C#
A Field Initializer Cannot Reference the Non-Static Field, Method, or Property
Executenonquery: Connection Property Has Not Been Initialized
How to Dynamically Create ASP.NET Controls Within Dynamically Created ASP.NET Controls
How to Convert Rgb Color to Hsv
Change System Date Programmatically
Workaround for Lack of 'Nameof' Operator in C# for Type-Safe Databinding
How to Iterate Over Values of an Enum Having Flags