C# comes with 16 built-in predefined types, split into 13 simple types and 3 non-simple types. All names for predefined types are written entirely in lowercase.
graph TD
A[Predefined Types] --> B[Simple]
A --> C[object]
A --> D[string]
A --> E[dynamic]
B --> F[Non-numeric]
B --> G[Numeric]
F --> H[bool]
F --> I[char]
G --> J[Integer]
G --> K[Floating Point]
J --> L[8-Bit]
J --> M[16-Bit]
J --> N[32-Bit]
J --> O[64-Bit]
L --> P[sbyte]
L --> Q[byte]
M --> R[short]
M --> S[ushort]
N --> T[int]
N --> U[uint]
O --> V[long]
O --> W[ulong]
K --> X[decimal]
K --> Y[float]
K --> Z[double]
%% Set leaf nodes to green
style H fill:#90ee90
style I fill:#90ee90
style P fill:#90ee90
style Q fill:#90ee90
style R fill:#90ee90
style S fill:#90ee90
style T fill:#90ee90
style U fill:#90ee90
style V fill:#90ee90
style W fill:#90ee90
style X fill:#90ee90
style Y fill:#90ee90
style Z fill:#90ee90
style C fill:#90ee90
style D fill:#90ee90
style E fill:#90ee90
13 Simple Types
- Numeric types (11 total) – 8 integer variants:
sbyte/byte, short/ushort, int/uint, long/ulong; 3 floating-point variants:float, double, decimal(decimal is designed exclusively for high-precision monetary calculations) - Non-numeric types (2 total):
char(single Unicode character),bool(only accepts true or false)
Key trait: Unlike C/C++, numeric values in C# cannot be directly used as boolean conditions in judgments.
3 Non-Simple Reference Types
string (sequence of characters), object (base class of all types), dynamic (for interoperability with dynamic languages)
C# Types vs .NET Types
Every predefined C# type maps directly to an underlying .NET type. C# type keywords are merely aliases for their corresponding .NET counterparts. Code compiles normally if you use the full native .NET type names, yet official coding guidelines discourage this practice. When writing C# code, always prefer the built-in C# keyword aliases over complete .NET class names.
Predefined Simple Types
| C# Keyword | Description | Value Range | Underlying .NET Type | Default Value |
|---|---|---|---|---|
| sbyte | 8-bit signed integer | -128 ~ 127 | System.SByte | 0 |
| byte | 8-bit unsigned integer | 0 ~ 255 | System.Byte | 0 |
| short | 16-bit signed integer | -32768 ~ 32767 | System.Int16 | 0 |
| ushort | 16-bit unsigned integer | 0 ~ 65535 | System.UInt16 | 0 |
| int | 32-bit signed integer | -2147483648 ~ 2147483647 | System.Int32 | 0 |
| uint | 32-bit unsigned integer | 0 ~ 4294967295 | System.UInt32 | 0 |
| long | 64-bit signed integer | -9223372036854775808 ~ 9223372036854775807 | System.Int64 | 0 |
| ulong | 64-bit unsigned integer | 0 ~ 18446744073709551615 | System.UInt64 | 0 |
| float | Single-precision floating point | 1.5×10⁻⁴⁵ ~ 3.4×10³⁸ | System.Single | 0.0f |
| double | Double-precision floating point | 5×10⁻³²⁴ ~ 1.7×10³⁰⁸ | System.Double | 0.0d |
| bool | Boolean type | true / false | System.Boolean | false |
| char | Unicode character | U+0000 ~ U+FFFF | System.Char | \x0000 (null character) |
| decimal | High-precision decimal value (28 significant digits) | ±1.0×10⁻²⁸ ~ ±7.9×10²⁸ | System.Decimal | 0m |
Predefined Non-Simple Types
| C# Keyword | Description | Underlying .NET Type |
|---|---|---|
| object | Base class for all types, including simple value types | System.Object |
| string | Text made of zero or more Unicode characters | System.String |
| dynamic | Dynamic type for compatibility with dynamic language assemblies | No fixed corresponding .NET type |
int is completely equivalent to System.Int32, and string matches System.String; the compiler recognizes and converts between them automatically.
Coding standards strongly recommend using native C# keywords (use int instead of Int32) to boost code readability.
Simple types are also known as Value Types.
They hold a single value and get allocated on the stack memory;
If declared without manual assignment, they automatically receive the default value listed in the table;
All simple types inherit directly from object and support boxing and unboxing operations (covered later in this guide).
Integer Family
- Types prefixed with
u(uint/ushort/ulong/byte) are unsigned, only storing non-negative numbers; - sbyte/short/int/long are signed, supporting both positive and negative integer values.
Floating-Point Family
float: Single precision with suffixf. Faster calculations at lower precision, ideal for graphics and 3D rendering;double: Double precision with suffixd. Default literal floating-point type for general scientific computation;decimal: High-precision decimal marked with suffixm. Built for financial and currency logic with no floating-point precision loss.
Boolean & Character Types
bool: Only two possible values; no implicit conversion allowed between boolean and numeric values;char: Stores one single Unicode character, internally represented as a 16-bit unsigned integer.
Non-Simple Types (Reference Types)
- object: Root base type. Every value and reference type derives from it; core component of the boxing mechanism;
- string: Special immutable reference type. Empty string literal
""counts as a valid default instance; - dynamic: Skips compile-time type validation and resolves members during runtime. No fixed .NET mapping, mainly used to integrate with dynamic languages like Python or Ruby, trading compile-time safety for greater flexibility.
static void Main(string[] args)
{
// 1. 8-bit integers
sbyte sByteNum = -60;
byte byteNum = 200;
// 2. 16-bit integers
short shortNum = -12000;
ushort uShortNum = 50000;
// 3. 32-bit integers
int intNum = -888888;
uint uIntNum = 3000000000U;
// 4. 64-bit integers
long longNum = -7000000000000L;
ulong uLongNum = 12000000000000000UL;
// 5. Floating-point types
float floatNum = 3.14f;
double doubleNum = 2.71828;
decimal decMoney = 999.99m;
// 6. Boolean type
bool flag = true;
// 7. Unicode character
char ch = 'A';
// 8. Predefined non-simple types
object obj = 123;
string str = "FOXDEVELOP.COM";
dynamic dy = "jack";
}Code language: C# (cs)
Built-in Types