Most programming languages support display conversion, also known as coercion, which corresponds to implicit conversion. For example, in general, integer can be implicitly converted to floating-point type, while floating-point type needs to be converted to integer through coercion:
int i = 32; double d = i;//Implicit conversion of integer to floating point int j = (int)d;//Convert floating point display to integer
Currently, the following implicit transformations are available in C #:
1. All implicit conversions
Implicit conversion is automatically completed, and implicit conversion also supports forced conversion, which is understandable.
2. Explicit numeric type conversion
Explicit numeric conversion includes:
1,sbyte Types can be explicitly converted to byte, ushort, uint, ulong, char. 2,byte Types can be explicitly converted to sbyte, char. 3,short Types can be explicitly converted to sbyte, byte, ushort, uint, ulong, char. 4,ushort Types can be explicitly converted to sbyte, byte, short, or char. 5,int Types can be explicitly converted to sbyte, byte, short, ushort, uint, ulong, char. 6,uint Types can be explicitly converted to sbyte, byte, short, ushort, int, char. 7,long Types can be explicitly converted to sbyte, byte, short, ushort, int, uint, ulong, char. 8,ulong Types can be explicitly converted to sbyte, byte, short, ushort, int, uint, long, char. 9,char Types can be explicitly converted to sbyte, byte, or short. 10,float Types can be explicitly converted to sbyte, byte, short, ushort, int, uint, long, ulong, char, decimal. 11,double Types can be explicitly converted to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, decimal. 12,decimal Types can be explicitly converted to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double.
It should be noted that when converting numeric types, precision may be lost or exceptions may be thrown. The conversion rules are as follows:
- The conversion of integer data to another integer data depends on whether checked and unchecked context detection is used:
For example: integer( S)Explicitly convert to integer( T) 1,use checked When context detection, when S Data in T Within the allowable range, the conversion can be carried out successfully, otherwise thrown System.OverflowException 2,use unchecked During context detection: When S The number of digits is greater than T The extra high bits (binary) will be intercepted during conversion, and the remaining bits will be used as T data output When S The number of digits is less than T When the number of bits is, the S Expand the data (binary) (unsigned integers use 0 to expand, signed integers use 1 to expand if less than 0, otherwise use 0 to expand), and take the expanded value as T data output When S Number of digits and T When the number of bits is equal, there is no need to intercept or expand, S Direct conversion of data to T data 3,not used checked and unchecked During context detection, the default context detection method (generally unchecked)
For example:
//--------------------------------------checked Context detection-------------------------------------------------- long l1 = 100000L; int value1 = checked((int)l1); //Normal conversion int value2 = checked((int)(l1 * l1));//report errors OverflowException //--------------------------------------unchecked Context detection-------------------------------------------------- long l2 = 100000L * 100000L;//10000000000 int value3 = unchecked((int)l2);//1410065408 //long It's 64 bit>int 32 bits, l2 Binary: 0100101010000001011111001000000000 //Intercept the extra three high bits to obtain the remaining 32-bit binary: 010101000000101111100100000000, i.e. 1410065408 sbyte b = -1;//Signed 8-bit uint value4 = unchecked((uint)b);//4294967295 //sbyte It's eight<uint 32 bits, b Binary: 1111111111111111111 //because sbyte Is a signed integer and b<0,Therefore, use 1 to expand the high bit to get 32-bit binary: 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 uint ui = 3147483647; int value5 = unchecked((int)ui);//-1147483649 //uint It's 32 bits=int 32 bits, ui Binary: 10111011100110101100100111111111 //So directly int Binary: 10111011100110101100100111111111, i.e-1147483649
- When a decimal floating-point number is forcibly converted to integer data, it will round to zero and discard the decimal part. If the rounded value is not within the range allowed by the conversion type, it will throw system Overflow exception, for example:
decimal d1 = 1.6m; decimal d2 = -1.6m; decimal d3 = 314m; sbyte b1 = (sbyte)d1;//1 sbyte b2 = (sbyte)d2;//-1 sbyte b3 = (sbyte)d3;//report errors System.OverflowException
- When converting float and double to integer data, it depends on whether checked and unchecked context detection is used:
1,use checked Context detection: If float perhaps double Value is NaN Or infinity( NegativeInfinity and PositiveInfinity),Will be thrown System.OverflowException Otherwise it will float perhaps double The value is rounded to zero and the decimal part is discarded. If the rounded value is not within the allowable range of integer type, it will be thrown System.OverflowException 2,use unchecked During context detection: If float perhaps double Value is NaN Or infinity( NegativeInfinity and PositiveInfinity),The conversion is cancelled and the default value of the integer is returned Otherwise it will float perhaps double The value is rounded to zero and the decimal part is discarded. If the rounded value is not within the allowable range of integer type, the conversion will be cancelled and the default value of integer type will be returned(The official documents are inaccurate. See the following example) 3,not used checked and unchecked During context detection, the default context detection method (generally unchecked)
For example:
double d1 = double.NaN; double d2 = 1.6d; double d3 = -1.6d; double d4 = 3147483647.25d; double d5 = 314.25d; //--------------------------checked Context detection---------------------------------- sbyte b1 = checked((sbyte)d1);//report errors System.OverflowException sbyte b2 = checked((sbyte)d2);//1 sbyte b3 = checked((sbyte)d3);//-1 sbyte b4 = checked((sbyte)d4);//report errors System.OverflowException //--------------------------unchecked Context detection-------------------------------- sbyte b5 = unchecked((sbyte)double.PositiveInfinity); //0 sbyte b6 = unchecked((sbyte)2.5d); //2 sbyte b7 = unchecked((sbyte)-3.5d); //-3 sbyte b8 = unchecked((sbyte)314.25d); //0 byte b9 = unchecked((byte)257.25d); //0 short b10 = unchecked((short)3147483647.25d); //0 int b11 = unchecked((int)3147483647.25d); //0 //The following is different from the official document (find out the reason when you have time. It may be a problem with the settings at compile time and runtime) int b12 = unchecked((int)d4); //-2147483648 sbyte b13 = unchecked((sbyte)d5); //58
- When double is cast to float, follow the rules:
1,Normally, double The value is passed to the nearest float Values are rounded (not rounded) to ensure that the loss of accuracy is relatively small 2,If one double The value of infinity tends to 0 when the precision exceeds float Allowable accuracy( float.Epsilon),Will+0 perhaps-0 Returned as a result, depending on double Is it positive or negative 3,If one double The value is very large, greater than float Returns infinity to the allowed range( float.NegativeInfinity perhaps float.PositiveInfinity,It depends on double (positive or negative)
For example:
double d0 = 3.1415d; double d1 = 3.141592653589793d; double d2 = double.NaN; double d3 = 3.14E-100d; double d4 = -3.14E-100d; double d5 = double.MaxValue; double d6 = double.MinValue; float f0 = (float)d0;//3.1415 float f1 = (float)d1;//3.1415927 float f2 = (float)d2;//NaN float f3 = (float)d3;//+0 float f4 = (float)d4;//-0 float f5 = (float)d5;//float.PositiveInfinity float f6 = (float)d6;//float.NegativeInfinity
-
When double and float are forcibly converted to decimal, follow the rules:
1,In general, double and float Values are converted directly to decimal,When the small data exceeds 28 bits, it will be automatically selected if necessary 2,If double and float If the value is too small and tends to 0, 0 will be returned directly 3,If double and float Value is NaN,Infinity, or more than decimal Run range, then it will be thrown System.OverflowException
For example:
double d0 = 3.1415d; double d1 = 3.14159265358979323d; double d2 = double.NaN; double d3 = 3.14E-200d; double d4 = -3.14E-200d; double d5 = double.MaxValue; double d6 = double.MinValue; decimal value0 = (decimal)d0;//3.1415 decimal value1 = (decimal)d1;//3.14159265358979 decimal value2 = (decimal)d2;//Throw System.OverflowException decimal value3 = (decimal)d3;//0 decimal value4 = (decimal)d4;//0 decimal value5 = (decimal)d5;//Throw System.OverflowException decimal value6 = (decimal)d6;//Throw System.OverflowException
-
When a decimal is forcibly converted to double or float, it can be converted successfully without throwing any exceptions, but it may cause the loss of precision, for example:
decimal d0 = 3.1415m; decimal d1 = 3.14159265358979323m; float value0 = (float)d0;//3.1415 float value1 = (float)d1;//3.1415927
3. Explicit enumeration type conversion
Explicit enumeration type conversions include:
1,sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal Can be explicitly converted to any enumeration type. 2,Any enumeration type can be explicitly converted to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal. 3,Explicit conversions can be made between any two enumeration types.
In fact, the bottom layer of enumeration type is still integer data, that is to say, the display conversion of enumeration type is essentially the forced conversion of integer data.
4. Explicit nullable type conversion
Explicit nullable type conversion means that if one value type S can be explicitly converted to another value type T, the following explicit conversions exist for S and T:
1,S? Can be explicitly converted to T?,If S?The value of is null,So after conversion T?Also null,Otherwise equivalent to S?->S->T->T? Process of 2,S Can be explicitly converted to T?,This is equivalent to S->T->T? Process of 3,S? Can be explicitly converted to T,If S?The value of is null,Will be thrown System.InvalidOperationException,Otherwise equivalent to S->T Process of
5. Explicit reference conversion
Explicit reference transformations include:
1,object and dynamic You can convert an explicit reference to any other reference type 2,The base class (parent class) can be converted into a subclass by explicit reference 3,Any non sealed A class can be converted to any interface by explicit reference, regardless of whether the class implements the interface or not 4,Any interface can be converted to any non interface by explicit reference sealed Class, whether or not the class implements the interface 5,Any interface can be converted to any interface by explicit reference, whether they are parent-child interface or not 6,If there is an explicit reference conversion between any two reference types, the arrays of the same dimension can also be converted by explicit reference 7,System.Array That is, the interface it implements(as System.Collections.IList),You can convert an explicit reference to any array type 8,If a type S To another type T If there is an explicit reference transformation, then S One dimensional array of S[]reach System.Collections.Generic.IList<T>And its parent interface (e.g System.Collections.Generic.ICollection<T>)There are also explicit reference transformations 9,If a type S To another type T If there is an explicit reference transformation, then System.Collections.Generic.IList<S>And its parent interface (e.g System.Collections.Generic.ICollection<S>)reach T One dimensional array of T[]There are also explicit reference transformations 10,System.Delegate And all the interfaces it implements can be explicitly referenced and converted to any delegate type 11,If a reference type T1 There is an explicit reference conversion to a reference type T2,T2 Existence ID conversion to T3,that T1 You can also convert to by explicit reference T3 12,If a reference type T1 There is an explicit reference to convert to an interface or delegate type T2,and T2 And T3 There is covariance, inversion or invariance between, then T1 You can also convert to by explicit reference T3 14,If D<X1,X2,...,Xn>Is a generic delegate type when Xi If one of the following conditions is met, then D<S1,S2...Sn>reach D<T1,T2...Tn>There are explicit reference transformations: Xi Is constant, and Si reach Ti identical Xi Is covariant, and Si reach Ti There are explicit and implicit identity or reference transformations Xi Yes, and Si and Ti Either the same or both reference types
Simple example:
public class Parent { } public class Child : Parent { } public interface IPerson { } public interface IAnimal { } object obj = null; Parent parent = (Parent)obj; //object and dynamic You can convert an explicit reference to any other reference type Child child = (Child)parent; //The base class (parent class) can be converted into a subclass by explicit reference IPerson person = (IPerson)child; //Any non sealed A class can be converted to any interface by explicit reference, regardless of whether the class implements the interface or not Exception exception = (Exception)person;//Any interface can be converted to any non interface by explicit reference sealed Class, whether or not the class implements the interface IAnimal animal = (IAnimal)person; //Any interface can be converted to any interface by explicit reference, whether they are parent-child interface or not //If there is an explicit reference conversion between any two reference types, the arrays of the same dimension can also be converted by explicit reference IAnimal[] animals = (IAnimal[])new IPerson[0]; IPerson[,] persons = (IPerson[,])new IAnimal[1, 2]; //System.Array That is, the interface it implements(as System.Collections.IList),You can convert an explicit reference to any array type Array array = null; IList list = null; int[] ints = (int[])array; double[,] doubles = (double[,])list; //If a type S To another type T If there is an explicit reference transformation, then S One dimensional array of S[]reach System.Collections.Generic.IList<T>And its parent interface (e.g System.Collections.Generic.ICollection<T>)There are also explicit reference transformations Parent[] parents = null; IList<Child> children = (IList<Child>)parents; ICollection<Child> children1 = (ICollection<Child>)parents; //And vice versa: if a type S To another type T If there is an explicit reference transformation, then System.Collections.Generic.IList<S>And its parent interface (e.g System.Collections.Generic.ICollection<S>)reach T One dimensional array of T[]There are also explicit reference transformations parents = (Parent[])children; parents = (Parent[])children1; //System.Delegate And all the interfaces it implements can be explicitly referenced and converted to any delegate type Delegate @delegate = null; ICloneable cloneable = null; Func<int> func = (Func<int>)@delegate; Action action = (Action)cloneable; //If a reference type T1 There is an explicit reference to convert to an interface or delegate type T2,and T2 And T3 There is covariance, inversion or invariance between, then T1 You can also convert to by explicit reference T3 Array array1 = new Child[0]; IEnumerable<Parent> parents1 = (IEnumerable<Parent>)array1;//System.Array You can convert an explicit reference to Child[],and Child[]reach IEnumerable<Parent>There is covariance //If D<X1,X2,...,Xn>Is a generic delegate type when Xi If one of the following conditions is met, then D<S1,S2...Sn>reach D<T1,T2...Tn>There are explicit reference transformations: //Xi Is constant, and Si reach Ti identical //Xi Is covariant, and Si reach Ti There are explicit and implicit identity or reference transformations //Xi Yes, and Si and Ti Either the same or both reference types Func<Parent, Child> func1 = p => (Child)p; Func<Child, Parent> func2 = (Func<Child, Parent>)func1;
Note: because the explicit reference conversion is checked at run time, we try to ensure that the value to be converted is null or convertible, otherwise system. Will be thrown InvalidCastException
6. Unpacking and conversion
Boxing conversion allows you to package a value type into a reference type for use. On the contrary, unpacking conversion unpacks the reference type to get the value type inside. At present, unpacking conversion includes:
1,object Can be unpacked and converted to value type 2,System.ValueType Can be unpacked and converted to any value type. 3,Any interface can be unpacked and converted to a non null value type that implements this interface 4,Any interface can be unpacked and converted to an nullable type that implements the value type of the interface 5,System.Enum Can be unpacked and converted to any enumeration type 6,System.Enum Nullable types that can be unpacked and converted to any enumerated type
For example
object obj = 1; ValueType value = 2L; int i = (int)obj; //object Can be unpacked and converted to value type long l = (long)value; //System.ValueType Can be unpacked and converted to any value type IFormattable formattable = 3.14f; float s = (float)formattable; //Any interface can be unpacked and converted to a non null value type that implements this interface float? nullable_s = (float?)formattable;//Any interface can be unpacked and converted to an nullable type that implements the value type of the interface Enum @enum = DayOfWeek.Monday; DayOfWeek dayOfWeek1 = (DayOfWeek)@enum; //System.Enum Can be unpacked and converted to any enumeration type DayOfWeek? dayOfWeek2 = (DayOfWeek?)@enum; //System.Enum Nullable types that can be unpacked and converted to any enumerated type
Note: because the unpacking conversion is checked at runtime, we should try our best to ensure that it is unpackable. If a null value is unpacked to a non empty value object, system. Will be thrown Nullreferenceexception. If the unpacked value is not the appropriate type, system. Exception will be thrown InvalidCastException.
7. Explicit dynamic conversion
Explicit dynamic conversion means that dynamic can be explicitly converted to any other type. It should be noted that it checks the conversion at runtime. If the conversion fails, an exception will be thrown.
dynamic @dynamic = 3.14f; long l = (long)@dynamic;//Can be explicitly and dynamically converted int i = @dynamic;//An error will be reported during operation, float Cannot be implicitly converted to int
Generally, if the type saved by the dynamic object is not the required type, it will first convert the dynamic to the object, and then convert the object to the required type. That is, if type S can be explicitly converted to T, then S can also be explicitly converted to T.
8. Explicit conversion involving type parameters
This generally refers to the conversion of generic parameters. In fact, explicit conversion works on generic types. Refer to the following examples:
public class Parent { public static explicit operator string(Parent parent) => parent?.ToString(); } public class Demo { public int E<T>(T t) { return (int)t;//An error was reported because the generic type is not known T What type is it } public int F<T>(T t) { return (int)(object)t;//You can write this without reporting an error } public string G<T>(T t) where T : Parent { return (string)t;//Can be converted, Parent Class has custom conversion to string } }
9. User defined explicit conversion
C # allows users to customize the conversion of types or structures. You can see: C# custom transformation (implicit or explicit)
Reference documents: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#explicit-conversions