The following conversions are classified as explicit conversions:
?All implicit conversions.
?Explicit numeric conversions.
?Explicit enumeration conversions.
?Explicit reference conversions.
?Explicit interface conversions.
?Unboxing conversions.
?User-defined explicit conversions.
Explicit conversions can occur in cast expressions (?4.6.6).
The set of explicit conversions includes all implicit conversions. [Note:
This means that redundant cast
expressions are allowed. end note]
The explicit conversions that are not implicit conversions are conversions
that cannot be proven to always
succeed, conversions that are known to possibly lose information, and
conversions across domains of types
sufficiently different to merit explicit notation.
13.2.1 Explicit numeric conversions
The explicit numeric conversions are the conversions from a numeric-type to
another numeric-type for
which an implicit numeric conversion (?3.1.2) does not already exist:
?From sbyte to byte, ushort, uint, ulong, or char.
?From byte to sbyte and char.
?From short to sbyte, byte, ushort, uint, ulong, or char.
?From ushort to sbyte, byte, short, or char.
?From int to sbyte, byte, short, ushort, uint, ulong, or char.
?From uint to sbyte, byte, short, ushort, int, or char.
?From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
?From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
?From char to sbyte, byte, or short.
?From float to sbyte, byte, short, ushort, int, uint, long, ulong, char,
or decimal.
?From double to sbyte, byte, short, ushort, int, uint, long, ulong, char,
float, or decimal.
C# LANGUAGE SPECIFICATION
116
?From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char,
float, or double.
Because the explicit conversions include all implicit and explicit numeric
conversions, it is always possible
to convert from any numeric-type to any other numeric-type using a cast
expression (?4.6.6).
The explicit numeric conversions possibly lose information or possibly
cause exceptions to be thrown. An
explicit numeric conversion is processed as follows:
?For a conversion from an integral type to another integral type, the
processing depends on the overflow
checking context (?4.5.12) in which the conversion takes place:
In a checked context, the conversion succeeds if the value of the source
operand is within the range of the
destination type, but throws a System.OverflowException if the value of the
source operand is outside
the range of the destination type.
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 signextended
or zero-extended so that it is 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
?For a conversion from decimal to an integral type, the source value is
rounded towards zero to the
nearest integral value, and this integral value becomes the result of the
conversion. If the resulting
integral value is outside the range of the destination type, a
System.OverflowException is thrown.
?For a conversion from float or double to an integral type, the processing
depends on the overflowchecking
context (?4.5.12) in which the conversion takes place:
In a checked context, the conversion proceeds as follows:
?The value is rounded towards zero to the nearest integral value. If this
integral value is within
the range of the destination type, then this value is the result of the
conversion.
?Otherwise, a System.OverflowException is thrown.
In an unchecked context, the conversion always succeeds, and proceeds as
follows.
?The value is rounded towards zero to the nearest integral value. If this
integral value is within
the range of the destination type, then this value is the result of the
conversion.
?Otherwise, the result of the conversion is an unspecified value of the
destination type.
?For a conversion from double to float, the double value is rounded to the
nearest float value. If
the double value is too small to represent as a float, the result becomes
positive zero or negative zero.
If the double value is too large to represent as a float, the result
becomes positive infinity or negative
infinity. If the double value is NaN, the result is also NaN.
?For a conversion from float or double to decimal, the source value is
converted to decimal
representation and rounded to the nearest number after the 28th decimal
place if required (?1.1.6). If the
source value is too small to represent as a decimal, the result becomes
zero. If the source value is NaN,
infinity, or too large to represent as a decimal, a
System.OverflowException is thrown.
?For a conversion from decimal to float or double, the decimal value is
rounded to the nearest
double or float value. While this conversion may lose precision, it never
causes an exception to be
thrown.
13.2.2 Explicit enumeration conversions
The explicit enumeration conversions are:
?From sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double, or decimal to
any enum-type.
?From any enum-type to sbyte, byte, short, ushort, int, uint, long, ulong,
char, float,
double, or decimal.
?From any enum-type to any other enum-type.
An explicit enumeration conversion between two types is processed by
treating any participating enum-type
as the underlying type of that enum-type, and then performing an implicit
or explicit numeric conversion
between the resulting types. [Example: For example, given an enum-type E
with and underlying type of int,
a conversion from E to byte is processed as an explicit numeric conversion (
?3.2.1) from int to byte,
and a conversion from byte to E is processed as an implicit numeric
conversion (?3.1.2) from byte to
int. end example]
13.2.3 Explicit reference conversions
The explicit reference conversions are:
?From object to any reference-type.
?From any class-type S to any class-type T, provided S is a base class of
T.
?From any class-type S to any interface-type T, provided S is not sealed
and provided S does not
implement T.
?From any interface-type S to any class-type T, provided T is not sealed
or provided T implements S.
?From any interface-type S to any interface-type T, provided S is not
derived from T.
?From an array-type S with an element type SE to an array-type T with an
element type TE, provided all
of the following are true:
S and T differ only in element type. (In other words, S and T have the same
number of dimensions.)
Both SE and TE are reference-types.
An explicit reference conversion exists from SE to TE.
?From System.Array and the interfaces it implements, to any array-type.
?From System.Delegate and the interfaces it implements, to any
delegate-type.
The explicit reference conversions are those conversions between
reference-types that require run-time
checks to ensure they are correct.
For an explicit reference conversion to succeed at run-time, the value of
the source operand must be null,
or the actual type of the object referenced by the source operand must be a
type that can be converted to the
destination type by an implicit reference conversion (?3.1.4). If an
explicit reference conversion fails, a
System.InvalidCastException is thrown.
Reference conversions, implicit or explicit, never change the referential
identity of the object being
converted. [Note: In other words, while a reference conversion may change
the type of the reference, it never
changes the type or value of the object being referred to. end note]
13.2.4 Unboxing conversions
An unboxing conversion permits an explicit conversion from type object or
System.ValueType to any
value-type, or from any interface-type to any value-type that implements
the interface-type. An unboxing
operation consists of first checking that the object instance is a boxed
value of the given value-type, and then
copying the value out of the instance. A struct can be unboxed from the
type System.ValueType, since
that is a base class for all structs (?8.3.2).
Unboxing conversions are described further in ?1.3.2.
13.2.5 User-defined explicit conversions
A user-defined explicit conversion consists of an optional standard
explicit conversion, followed by
execution of a user-defined implicit or explicit conversion operator,
followed by another optional standard
explicit conversion. The exact rules for evaluating user-defined
conversions are described in ?3.4.4.