Since C# is statically typed at compile time, variables cannot be declared again after being declared, or values of another type cannot be assigned unless the type can be implicitly converted to the type of the variable. For example, string cannot be implicitly converted to int. Therefore, after declaring i as int, the string "Hello" cannot be assigned to it, as shown in the following code:
int i; // error CS0029: Cannot implicitly convert type 'string' to 'int' i = "Hello";
But sometimes it may be necessary to copy the value into other types of variables or method parameters. For example, you might need to pass an integer variable to a method that has a parameter typed to double. Or you may need to assign class variables to variables of interface type. These types of operations are called type conversions. In C#, the following types of conversions can be performed:
- Implicit Conversion: Since this conversion will always succeed and will not result in data loss, there is no need to use any special syntax. Examples include conversions from smaller integer types to larger integer types and conversions from derived classes to base classes.
- Explicit conversion (Capt): A cast expression must be used to perform an explicit conversion. A cast must be done when information may be lost in the conversion or when the conversion may not be successful for other reasons. Typical examples include conversions from numerical values to types with lower precision or smaller range and conversions from base class instances to derived classes.
- User-defined conversion: User-defined conversions are performed using special methods that can be defined as enabling explicit and implicit conversions between custom types without base class and derived class relationships.
- Convert with helper classes: To convert between non-compatible types such as integers and objects, or hexadecimal strings and byte arrays, you can use the Parse methods of the class, class, and built-in numeric types (such as ).
Implicit conversion
For built-in numeric types, implicit conversions can be performed if the value to be stored is adapted to the variable without truncating or rounding. For integer types, this means that the scope of the source type is the correct subset of the scope of the target type. For example, a variable of type long (64-bit integer) can store any value that an int (32-bit integer) can store. In the following example, the compiler first implicitly converts the num value on the right to a long type, and assigns it to bigNum.
// Implicit conversion. A long can // hold any value an int can hold, and more! int num = 2147483647; long bigNum = num;
For a complete list of all implicit numerical conversions, see the article Built-in numerical conversionsImplicit numerical conversion table part。
For reference types, implicit conversions always exist in the case where a conversion from a class to any direct or indirect base class or interface of that class. Since the derived class always contains all members of the base class, there is no need to use any special syntax.
Derived d = new Derived(); // Always OK. Base b = d;
Explicit conversion
However, if a conversion may result in information loss, the compiler will require an explicit conversion, also known as a cast. Casting is one way to explicitly tell the compiler that you intend to do the conversion and you know that data loss may occur, or you know that the cast may fail at runtime. To perform a cast, specify the type to cast in the parentheses before the value or variable you want to convert. The following program casts double to int. If the program is not cast, the program will not be compiled.
class Test { static void Main() { double x = 1234.7; int a; // Cast double to int. a = (int)x; (a); } } // Output: 1234
For a complete list of supported explicit numerical conversions, see the article Built-in numerical conversionsExplicit numerical conversion part。
For reference types, if you need to convert from the base type to the derived type, you must do an explicit cast:
// Create a new derived type. Giraffe g = new Giraffe(); // Implicit conversion to base type is safe. Animal a = g; // Explicit conversion is required to cast back // to derived type. Note: This will compile but will // throw an exception at run time if the right-side // object is not in fact a Giraffe. Giraffe g2 = (Giraffe)a;
The cast operation between reference types does not change the runtime type of the underlying object; it only changes the type of the value used as references to that object. For more information, seePolymorphism。
Type conversion exception at runtime
In some reference type conversions, the compiler cannot determine whether the cast will work. A cast operation that compiles correctly may fail at runtime. As shown in the following example, a type conversion fails at runtime will cause an InvalidCastException to be raised.
class Animal { public void Eat() => ("Eating."); public override string ToString() => "I am an animal."; } class Reptile : Animal { } class Mammal : Animal { } class UnSafeCast { static void Main() { Test(new Mammal()); // Keep the console window open in debug mode. ("Press any key to exit."); (); } static void Test(Animal a) { // at run time // Unable to cast object of type 'Mammal' to type 'Reptile' Reptile r = (Reptile)a; } }
The Test method has an Animal formal parameter, so explicitly casting the actual parameter a to Reptile creates a dangerous assumption. It is safer to do not make assumptions, but to check the type. C# provides the is operator, allowing you to test compatibility before actually performing a cast. For more information, see How toSafely cast using pattern matching and as and is operators。
The above is a detailed explanation of c# cast and type conversion. For more information about c# cast and type conversion, please pay attention to my other related articles!