强制转换和类型转换(C# 编程指南)Casting and type conversions (C# Programming Guide)

由于 C# 是在编译时静态类型化的,因此变量在声明后就无法再次声明,或无法分配另一种类型的值,除非该类型可以隐式转换为变量的类型。Because C# is statically-typed at compile time, after a variable is declared, it cannot be declared again or assigned a value of another type unless that type is implicitly convertible to the variable's type. 例如,string 无法隐式转换为 intFor example, the string cannot be implicitly converted to int. 因此,在将 i 声明为 int 后,无法将字符串“Hello”分配给它,如以下代码所示:Therefore, after you declare i as an int, you cannot assign the string "Hello" to it, as the following code shows:

int i;  
i = "Hello"; // error CS0029: Cannot implicitly convert type 'string' to 'int'

但有时可能需要将值复制到其他类型的变量或方法参数中。However, you might sometimes need to copy a value into a variable or method parameter of another type. 例如,可能需要将一个整数变量传递给参数类型化为 double 的方法。For example, you might have an integer variable that you need to pass to a method whose parameter is typed as double. 或者可能需要将类变量分配给接口类型的变量。Or you might need to assign a class variable to a variable of an interface type. 这些类型的操作称为类型转换。 These kinds of operations are called type conversions. 在 C# 中,可以执行以下几种类型的转换:In C#, you can perform the following kinds of conversions:

  • 隐式转换:由于这种转换是类型安全且不会导致数据丢失,因此无需使用任何特殊语法。Implicit conversions: No special syntax is required because the conversion is type safe and no data will be lost. 示例包括从较小整数类型到较大整数类型的转换以及从派生类到基类的转换。Examples include conversions from smaller to larger integral types, and conversions from derived classes to base classes.

  • 显式转换(强制转换) :必须使用强制转换运算符,才能执行显式转换。Explicit conversions (casts): Explicit conversions require a cast operator. 在转换中可能丢失信息时或在出于其他原因转换可能不成功时,必须进行强制转换。Casting is required when information might be lost in the conversion, or when the conversion might not succeed for other reasons. 典型的示例包括从数值到精度较低或范围较小的类型的转换和从基类实例到派生类的转换。Typical examples include numeric conversion to a type that has less precision or a smaller range, and conversion of a base-class instance to a derived class.

  • 用户定义的转换:用户定义的转换是使用特殊方法执行,这些方法可定义为在没有基类和派生类关系的自定义类型之间启用显式转换和隐式转换。User-defined conversions: User-defined conversions are performed by special methods that you can define to enable explicit and implicit conversions between custom types that do not have a base class–derived class relationship. 有关详细信息,请参阅用户定义转换运算符For more information, see User-defined conversion operators.

  • 使用帮助程序类进行转换:若要在非兼容类型(如整数和 System.DateTime 对象,或十六进制字符串和字节数组)之间转换,可使用 System.BitConverter 类、System.Convert 类和内置数值类型的 Parse 方法(如 Int32.Parse)。Conversions with helper classes: To convert between non-compatible types, such as integers and System.DateTime objects, or hexadecimal strings and byte arrays, you can use the System.BitConverter class, the System.Convert class, and the Parse methods of the built-in numeric types, such as Int32.Parse. 有关详细信息,请参阅如何:将字节数组转换为 int操作说明:将字符串转换为数字操作说明:在十六进制字符串与数值类型之间转换For more information, see How to: Convert a byte Array to an int, How to: Convert a String to a Number, and How to: Convert Between Hexadecimal Strings and Numeric Types.

隐式转换Implicit conversions

对于内置数值类型,如果要存储的值无需截断或四舍五入即可适应变量,则可以进行隐式转换。For built-in numeric types, an implicit conversion can be made when the value to be stored can fit into the variable without being truncated or rounded off. 对于整型类型,这意味着源类型的范围是目标类型范围的正确子集。For integral types, this means the range of the source type is a proper subset of the range for the target type. 例如,long 类型的变量(64 位整数)能够存储 int(32 位整数)可存储的任何值。For example, a variable of type long (64-bit integer) can store any value that an int (32-bit integer) can store. 在下面的示例中,编译器先将右侧的 num 值隐式转换为 long 类型,再将它赋给 bigNumIn the following example, the compiler implicitly converts the value of num on the right to a type long before assigning 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 numeric conversions, see Implicit Numeric Conversions Table.

对于引用类型,隐式转换始终存在于从一个类转换为该类的任何一个直接或间接的基类或接口的情况。For reference types, an implicit conversion always exists from a class to any one of its direct or indirect base classes or interfaces. 由于派生类始终包含基类的所有成员,因此不必使用任何特殊语法。No special syntax is necessary because a derived class always contains all the members of a base class.

Derived d = new Derived();  
Base b = d; // Always OK.  

显式转换Explicit conversions

但是,如果进行转换可能会导致信息丢失,则编译器会要求执行显式转换,显式转换也称为强制转换。 However, if a conversion cannot be made without a risk of losing information, the compiler requires that you perform an explicit conversion, which is called a cast. 强制转换是显式告知编译器你打算进行转换且你知道可能会发生数据丢失的一种方式。A cast is a way of explicitly informing the compiler that you intend to make the conversion and that you are aware that data loss might occur. 若要执行强制转换,请在要转换的值或变量前面的括号中指定要强制转换到的类型。To perform a cast, specify the type that you are casting to in parentheses in front of the value or variable to be converted. 下面的程序将 double 强制转换为 int。如不强制转换则该程序不会进行编译。The following program casts a double to an int. The program will not compile without the cast.

class Test
{
    static void Main()
    {
        double x = 1234.7;
        int a;
        // Cast double to int.
        a = (int)x;
        System.Console.WriteLine(a);
    }
}
// Output: 1234

有关支持的显式数值转换的列表,请参阅显式数值转换表For a list of the explicit numeric conversions that are allowed, see Explicit Numeric Conversions Table.

对于引用类型,如果需要从基类型转换为派生类型,则必须进行显式强制转换:For reference types, an explicit cast is required if you need to convert from a base type to a derived type:

// 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;  

引用类型之间的强制转换操作不会更改基础对象的运行时类型;它只更改用作对该对象引用的值的类型。A cast operation between reference types does not change the run-time type of the underlying object; it only changes the type of the value that is being used as a reference to that object. 有关详细信息,请参阅多态性For more information, see Polymorphism.

运行时的类型转换异常Type conversion exceptions at run time

在某些引用类型转换中,编译器无法确定强制转换是否会有效。In some reference type conversions, the compiler cannot determine whether a cast will be valid. 正确进行编译的强制转换操作有可能在运行时失败。It is possible for a cast operation that compiles correctly to fail at run time. 如下面的示例所示,类型转换在运行时失败将导致引发 InvalidCastExceptionAs shown in the following example, a type cast that fails at run time will cause an InvalidCastException to be thrown.


using System;

class Animal
{
    public void Eat() { Console.WriteLine("Eating."); }
    public override string ToString()
    {
        return "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.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    static void Test(Animal a)
    {
        // Cause InvalidCastException at run time 
        // because Mammal is not convertible to Reptile.
        Reptile r = (Reptile)a;
    }

}

C# 提供 is 运算符,使你可以在实际执行强制转换之前测试兼容性。C# provides the is operator to enable you to test for compatibility before actually performing a cast. 有关详细信息,请参阅操作说明:使用模式匹配以及 as 和 is 运算符安全地进行强制转换For more information, see How to: safely cast using pattern matching and the as and is operators.

C# 语言规范C# language specification

有关详细信息,请参阅 C# 语言规范中的转换部分。For more information, see the Conversions section of the C# language specification.

请参阅See also