The integral numeric types represent integer numbers. All integral numeric types are value types. The integral types are simple types and you initialize them with literals. All integral numeric types support arithmetic, bitwise logical, comparison, and equality operators.
ms.custom: "updateeachrelease"
The C# language reference documents the most recently released version of the C# language. It also contains initial documentation for features in public previews for the upcoming language release.
The documentation identifies any feature first introduced in the last three versions of the language or in current public previews.
Characteristics of the integral types
C# supports the following predefined integral types:
| C# type/keyword | Range | Size | .NET type |
|---|---|---|---|
sbyte |
-128 to 127 | Signed 8-bit integer | System.SByte |
byte |
0 to 255 | Unsigned 8-bit integer | System.Byte |
short |
-32,768 to 32,767 | Signed 16-bit integer | System.Int16 |
ushort |
0 to 65,535 | Unsigned 16-bit integer | System.UInt16 |
int |
-2,147,483,648 to 2,147,483,647 | Signed 32-bit integer | System.Int32 |
uint |
0 to 4,294,967,295 | Unsigned 32-bit integer | System.UInt32 |
long |
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | Signed 64-bit integer | System.Int64 |
ulong |
0 to 18,446,744,073,709,551,615 | Unsigned 64-bit integer | System.UInt64 |
nint |
Depends on platform (computed at runtime) | Signed 32-bit or 64-bit integer | System.IntPtr |
nuint |
Depends on platform (computed at runtime) | Unsigned 32-bit or 64-bit integer | System.UIntPtr |
In all of the table rows except the last two, each C# type keyword from the leftmost column is an alias for the corresponding .NET type. The keyword and .NET type name are interchangeable. For example, the following declarations declare variables of the same type:
int a = 123;
System.Int32 b = 123;The nint and nuint types in the last two rows of the table are native-sized integers. You can use the nint and nuint contextual keywords to define native-sized integers. Native-sized integers are 32-bit integers when running in a 32-bit process, or 64-bit integers when running in a 64-bit process. Use them for interop scenarios, low-level libraries, and to optimize performance in scenarios where integer math is used extensively.
The native-sized integer types are represented internally as the .NET types System.IntPtr and System.UIntPtr. The nint and nuint types are aliases for the underlying types.
The default value of each integral type is zero, 0.
Each of the integral types has MinValue and MaxValue properties that provide the minimum and maximum value of that type. These properties are compile-time constants except for the case of the native-sized types (nint and nuint). The MinValue and MaxValue properties are calculated at runtime for native-sized types. The sizes of those types depend on the process settings.
Use the System.Numerics.BigInteger structure to represent a signed integer with no upper or lower bounds.
Integer literals
Integer literals can be:
- decimal: without any prefix
- hexadecimal: with the
0xor0Xprefix - binary: with the
0bor0Bprefix
The following code demonstrates an example of each:
var decimalLiteral = 42;
var hexLiteral = 0x2A;
var binaryLiteral = 0b_0010_1010;The preceding example also shows the use of _ as a digit separator. You can use the digit separator with all kinds of numeric literals.
The suffix determines the type of an integer literal as follows:
If the literal has no suffix, the compiler assigns the type as the first of the following types in which its value can be represented:
int,uint,long,ulong.If the literal includes the
Uorusuffix, the compiler assigns the type as the first of the following types in which its value can be represented:uint,ulong.If the literal includes the
Lorlsuffix, the compiler assigns the type as the first of the following types in which its value can be represented:long,ulong.If the literal includes one of the
UL,Ul,uL,ul,LU,Lu,lU, orlusuffixes, the compiler assigns the type asulong.
If the value represented by an integer literal exceeds System.UInt64.MaxValue, a compiler error CS1021 occurs.
If the compiler determines the type of an integer literal as int and the value represented by the literal is within the range of the destination type, the value can be implicitly converted to sbyte, byte, short, ushort, uint, ulong, nint, or nuint:
byte a = 17;
byte b = 300; // CS0031: Constant value '300' cannot be converted to a 'byte'As the preceding example shows, if the literal's value isn't within the range of the destination type, a compiler error CS0031 occurs.
You can also use a cast to convert the value represented by an integer literal to the type other than the determined type of the literal:
var signedByte = (sbyte)42;
var longVariable = (long)42;Conversions
You can convert any integral numeric type to any other integral numeric type. If the destination type can store all values of the source type, the conversion is implicit. Otherwise, use a cast expression to perform an explicit conversion. For more information, see Built-in numeric conversions.
Native sized integers
Native sized integer types have special behavior because the storage matches the natural integer size on the target machine.
- To get the size of a native-sized integer at run time, use
sizeof(). However, the code must be compiled in an unsafe context. For example:
sample · csharpdocs/csharp/language-reference/builtin-types/snippets/shared/NativeIntegerTypes.csSizeOf
namespace builtin_types
{
public static class NativeIntegerTypes
{
public static void Examples()
{
nativeintegerminmax.Example.Main();
}
}
namespace nativeintegerminmax
{
public static class Example
{
public unsafe static void Main()
{
// <MinMax>
Console.WriteLine($"nint.MinValue = {nint.MinValue}");
Console.WriteLine($"nint.MaxValue = {nint.MaxValue}");
Console.WriteLine($"nuint.MinValue = {nuint.MinValue}");
Console.WriteLine($"nuint.MaxValue = {nuint.MaxValue}");
// output when run in a 64-bit process
//nint.MinValue = -9223372036854775808
//nint.MaxValue = 9223372036854775807
//nuint.MinValue = 0
//nuint.MaxValue = 18446744073709551615
// output when run in a 32-bit process
//nint.MinValue = -2147483648
//nint.MaxValue = 2147483647
//nuint.MinValue = 0
//nuint.MaxValue = 4294967295
// </MinMax>
// <SizeOf>
Console.WriteLine($"size of nint = {sizeof(nint)}");
Console.WriteLine($"size of nuint = {sizeof(nuint)}");
// output when run in a 64-bit process
//size of nint = 8
//size of nuint = 8
// output when run in a 32-bit process
//size of nint = 4
//size of nuint = 4
// </SizeOf>
}
}
}
}You can also get the equivalent value from the static System.IntPtr.Size and System.UIntPtr.Size properties.
- To get the minimum and maximum values of native-sized integers at run time, use
MinValueandMaxValueas static properties with thenintandnuintkeywords, as in the following example:
sample · csharpdocs/csharp/language-reference/builtin-types/snippets/shared/NativeIntegerTypes.csMinMax
namespace builtin_types
{
public static class NativeIntegerTypes
{
public static void Examples()
{
nativeintegerminmax.Example.Main();
}
}
namespace nativeintegerminmax
{
public static class Example
{
public unsafe static void Main()
{
// <MinMax>
Console.WriteLine($"nint.MinValue = {nint.MinValue}");
Console.WriteLine($"nint.MaxValue = {nint.MaxValue}");
Console.WriteLine($"nuint.MinValue = {nuint.MinValue}");
Console.WriteLine($"nuint.MaxValue = {nuint.MaxValue}");
// output when run in a 64-bit process
//nint.MinValue = -9223372036854775808
//nint.MaxValue = 9223372036854775807
//nuint.MinValue = 0
//nuint.MaxValue = 18446744073709551615
// output when run in a 32-bit process
//nint.MinValue = -2147483648
//nint.MaxValue = 2147483647
//nuint.MinValue = 0
//nuint.MaxValue = 4294967295
// </MinMax>
// <SizeOf>
Console.WriteLine($"size of nint = {sizeof(nint)}");
Console.WriteLine($"size of nuint = {sizeof(nuint)}");
// output when run in a 64-bit process
//size of nint = 8
//size of nuint = 8
// output when run in a 32-bit process
//size of nint = 4
//size of nuint = 4
// </SizeOf>
}
}
}
}While the full range of
nintandnuintcan be larger, compile-time constants are restricted to a 32-bit range:- For
nint: System.Int32.MinValue to System.Int32.MaxValue. - For
nuint: System.UInt32.MinValue to System.UInt32.MaxValue.
- For
The compiler provides implicit and explicit conversions to other numeric types. For more information, see Built-in numeric conversions.
There's no direct syntax for native-sized integer literals. There's no suffix to indicate that a literal is a native-sized integer, such as
Lto indicate along. Use implicit or explicit casts of other integer values instead. For example:nint a = 42 nint a = (nint)42;
C# language specification
For more information, see the following sections of the C# language specification: