Руководство по программированию на 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 невозможно неявно преобразовать в int.For 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 перед назначением bigNum.In 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. Как показано в следующем примере, приведение типа, завершившееся сбоем во время выполнения, вызывает исключение InvalidCastException.As 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. Дополнительные сведения см. в статье Практическое руководство. Безопасное приведение с помощью сопоставления шаблонов и операторы is и as.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