Built-in numeric conversions (C# reference)
C# provides a set of integral and floating-point numeric types. There exists a conversion between any two numeric types, either implicit or explicit. You must use a cast expression to perform an explicit conversion.
Implicit numeric conversions
The following table shows the predefined implicit conversions between the built-in numeric types:
From | To |
---|---|
sbyte | short , int , long , float , double , decimal , or nint |
byte | short , ushort , int , uint , long , ulong , float , double , decimal , nint , or nuint |
short | int , long , float , double , or decimal , or nint |
ushort | int , uint , long , ulong , float , double , or decimal , nint , or nuint |
int | long , float , double , or decimal , nint |
uint | long , ulong , float , double , or decimal , or nuint |
long | float , double , or decimal |
ulong | float , double , or decimal |
float | double |
nint | long , float , double , or decimal |
nuint | ulong , float , double , or decimal |
Note
The implicit conversions from int
, uint
, long
, ulong
, nint
, or nuint
to float
and from long
, ulong
, nint
, or nuint
to double
may cause a loss of precision, but never a loss of an order of magnitude. The other implicit numeric conversions never lose any information.
Also note that
Any integral numeric type is implicitly convertible to any floating-point numeric type.
There are no implicit conversions to the
byte
andsbyte
types. There are no implicit conversions from thedouble
anddecimal
types.There are no implicit conversions between the
decimal
type and thefloat
ordouble
types.A value of a constant expression of type
int
(for example, a value represented by an integer literal) can be implicitly converted tosbyte
,byte
,short
,ushort
,uint
,ulong
,nint
, ornuint
, if it's within the range of the destination type:byte a = 13; byte b = 300; // CS0031: Constant value '300' cannot be converted to a 'byte'
As the preceding example shows, if the constant value is not within the range of the destination type, a compiler error CS0031 occurs.
Explicit numeric conversions
The following table shows the predefined explicit conversions between the built-in numeric types for which there is no implicit conversion:
From | To |
---|---|
sbyte | byte , ushort , uint , ulong , or nuint |
byte | sbyte |
short | sbyte , byte , ushort , uint , ulong , or nuint |
ushort | sbyte , byte , or short |
int | sbyte , byte , short , ushort , uint , ulong , or nuint |
uint | sbyte , byte , short , ushort , int , or nint |
long | sbyte , byte , short , ushort , int , uint , ulong , nint , or nuint |
ulong | sbyte , byte , short , ushort , int , uint , long , nint , or nuint |
float | sbyte , byte , short , ushort , int , uint , long , ulong , decimal , nint , or nuint |
double | sbyte , byte , short , ushort , int , uint , long , ulong , float , decimal , nint , or nuint |
decimal | sbyte , byte , short , ushort , int , uint , long , ulong , float , double , nint , or nuint |
nint | sbyte , byte , short , ushort , int , uint , ulong , or nuint |
nuint | sbyte , byte , short , ushort , int , uint , long , or nint |
Note
An explicit numeric conversion might result in data loss or throw an exception, typically an OverflowException.
Also note that:
When you convert a value of an integral type to another integral type, the result depends on the overflow-checking context. In a checked context, the conversion succeeds if the source value is within the range of the destination type. Otherwise, an OverflowException is thrown. In an unchecked context, the conversion always succeeds, and proceeds as follows:
If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. The result is then treated as a value of the destination type.
If the source type is smaller than the destination type, then the source value is either sign-extended or zero-extended so that it's of the same size as the destination type. Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. The result is then treated as a value of the destination type.
If the source type is the same size as the destination type, then the source value is treated as a value of the destination type.
When you convert a
decimal
value to an integral type, this value is rounded towards zero to the nearest integral value. If the resulting integral value is outside the range of the destination type, an OverflowException is thrown.When you convert a
double
orfloat
value to an integral type, this value is rounded towards zero to the nearest integral value. If the resulting integral value is outside the range of the destination type, the result depends on the overflow-checking context. In a checked context, an OverflowException is thrown, while in an unchecked context, the result is an unspecified value of the destination type.When you convert
double
tofloat
, thedouble
value is rounded to the nearestfloat
value. If thedouble
value is too small or too large to fit into thefloat
type, the result is zero or infinity.When you convert
float
ordouble
todecimal
, the source value is converted todecimal
representation and rounded to the nearest number after the 28th decimal place if necessary. Depending on the value of the source value, one of the following results may occur:If the source value is too small to be represented as a
decimal
, the result becomes zero.If the source value is NaN (not a number), infinity, or too large to be represented as a
decimal
, an OverflowException is thrown.
When you convert
decimal
tofloat
ordouble
, the source value is rounded to the nearestfloat
ordouble
value, respectively.
C# language specification
For more information, see the following sections of the C# language specification: