#Java starts the names of primitive types with lower-case letters and all others with upper-case letters.
#Csharp *could* do that.
Or, reasonably, it could use capitalization to distinguish between value types (like ints and structs) and reference types (like classes).
But no. C# uses this to indicate whether a type is *predefined*. So string and object, unlike all other classes, start with lower-case letters.
Worse, string and object are actually aliases for System.String and System.Object, respectively.
Why would you add aliases to make things *less* consistent?
> But no. C# uses this to indicate whether a type is *predefined*.
Sorry but that is not correct. Rather C# has keyword aliases for a few very commonly used types. Eg. `int` is an alias for `System.Int32` which you can see the definition of https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Int32.cs.
(Additionally, just to add confusion, there is direct support for some types like Int32 in the .NET intermediate language so both C# compiler and JIT special case.)
@richardcox13 I'm confused that the struct Int32 contains an int m_value as a field. If int is just an alias for Int32, isn't this recursive?
@peterdrake
That's the "additional, to add confusion..." bit. Storage and many operations on ints are inbuilt to the compiler and JIT.
`int` keyword remains an alias for System.Int32, but the source of the type is the pieces the runtime doesn't have built in.
@peterdrake (pt 2): a better example would be "decimal" and "System.Decimal" as CPUs don't include operations for a type like decumal.
@peterdrake To be fair, *all* predefined types have associated upper-named classes, not just string and object. I.e. int has System.Int32