# Integral numeric types (C# reference)

The integral numeric types are a subset of the simple types and can be initialized with literals. All integral types are also value types. All integral numeric types support arithmetic, bitwise logical, comparison, and equality operators.

## 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

In the preceding table, each C# type keyword from the leftmost column is an alias for the corresponding .NET type. They are interchangeable. For example, the following declarations declare variables of the same type:

int a = 123;
System.Int32 b = 123;


The default value of each integral type is zero, 0. Each of the integral types has the MinValue and MaxValue constants that provide the minimum and maximum value of that type.

Use the System.Numerics.BigInteger structure to represent a signed integer with no upper or lower bounds.

## Integral literals

Integral literals can be specified as decimal literals, hexadecimal literals, or binary literals. An example of each is shown below:

var decimalLiteral = 42;
var hexLiteral = 0x2A;
var binaryLiteral = 0b_0010_1010;


Decimal literals don't require any prefix. The x or X prefix signifies a hexadecimal literal. The b or B prefix signifies a binary literal. The declaration of binaryLiteral demonstrates the use of _ as a digit separator. The digit separator can be used with all numeric literals. Binary literals and the digit separator _ are supported starting with C# 7.0.

### Literal suffixes

The l or L suffix specifies that the integral literal should be of the long type. The ul or UL suffix specifies the ulong type. If the L suffix is used on a literal that is greater than 9,223,372,036,854,775,807 (the maximum value of long), the value is converted to the ulong type. If the value represented by an integral literal exceeds UInt64.MaxValue, a compiler error CS1021 occurs.

Note

You can use the lowercase letter "l" as a suffix. However, this generates a compiler warning because the letter "l" is easily confused with the digit "1." Use "L" for clarity.

### Type of an integral literal

If an integral literal has no suffix, its type is the first of the following types in which its value can be represented:

1. int
2. uint
3. long
4. ulong

You can convert an integral literal to a type with a smaller range than the default using either an assignment or a cast:

byte byteVariable = 42; // type is byte
var signedByte = (sbyte)42; // type is sbyte.


You can convert an integral literal to a type with a larger range than the default using either assignment, a cast, or a suffix on the literal:

var unsignedLong = 42UL;
var longVariable = 42L;
ulong anotherUnsignedLong = 42;
var anotherLong = (long)42;


## Conversions

There's an implicit conversion (called a widening conversion) between any two integral types where the destination type can store all values of the source type. For example, there's an implicit conversion from int to long because the range of int values is a proper subset of long. There are implicit conversions from a smaller unsigned integral type to a larger signed integral type. There's also an implicit conversion from any integral type to any floating-point type. There's no implicit conversion from any signed integral type to any unsigned integral type.

You must use an explicit cast to convert one integral type to another integral type when an implicit conversion is not defined from the source type to the destination type. This is called a narrowing conversion. The explicit case is required because the conversion can result in data loss.