Приведение и преобразование типов (руководство по программированию в C#)
Обновлен: Июль 2008
Поскольку в C# тип определяется статически тип во время компиляции, после объявления переменной, она не может быть объявлена вновь или использоваться для хранения значений другого типа, если этот тип не преобразуется в тип переменной. Например, невозможно преобразование из целого числа в произвольную строку. Поэтому после объявления переменной i как целочисленной, нельзя ей присвоить строку "Hello", как показано в следующем коде.
int i;
i = "Hello"; // Error: "Cannot implicitly convert type 'string' to 'int'"
Но иногда может быть необходимым скопировать значение в переменную или параметр метода другого типа. Например, может быть переменная, которую требуется передать методу, параметр которого имеет тип double. Или может понадобиться присвоить переменную класса переменной типа интерфейса. Операции такого вида называются преобразованиями типов. В C# можно выполнять следующие виды преобразований:
Неявные преобразования. Не требуется никакого специального синтаксиса, поскольку преобразование безопасно для типов и данные не теряются. Примерами могут служить преобразования от меньшего к большему целому типу, и преобразования из производных классов в базовые классы.
Явные преобразования (приведения). Для явных преобразований необходим оператор приведения. Исходная переменная и переменная назначения совместимы, но имеется риск потери данных, поскольку тип переменной назначения имеет меньший размер, чем у исходной переменной (или является базовым классом исходной переменной).
Пользовательские преобразования. Пользовательские преобразования выполняются специальными методами, которые можно определить для включения явных и неявных преобразований между пользовательскими типами, не имеющих отношения базовый класс — производный класс. Дополнительные сведения см. в разделе Операторы преобразования (Руководство по программированию в C#).
Преобразования с помощью вспомогательных классов. Для преобразования между несовместимыми типами, например целые числа и объекты System.DateTime, или шестнадцатеричные строки и байтовые массивы, можно использовать класс System.BitConverter, класс System.Convert и методы Parse встроенных числовых типов, таких как Int32.Parse. Дополнительные сведения см. в разделах Практическое руководство. Преобразование массива байтов в значение типа "int" (Руководство по программированию на C#), Практическое руководство. Преобразование массива строки в значение типа "int" (Руководство по программированию в C#) и Практическое руководство. Преобразование из шестнадцатеричных строк в числовые типы (Руководство по программированию в C#).
Неявные преобразования
ля встроенных числовых типов неявное преобразование можно выполнить, сохраняемое значение может уместиться в переменной без обрезания или округления до ближайшего. Например, переменная типа longlong (справочник по C#) (8-байтное целое) может хранить любое значение, которое может хранить intint (справочник по C#) (4 байта в 32-разрядном компьютере). В следующем примере компилятор неявно преобразует значение справа в тип long перед присвоением его типу bigNum.
// Implicit conversion. num long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
Полный список всех неявных числовых преобразований см. в разделе Таблица неявных числовых преобразований (Справочник по C#).
Для ссылочных типов всегда существует неявное преобразование из класса в любой из его прямых или косвенных базовых классов или интерфейсов. Никакого специального синтаксиса не требуется, поскольку производный класс всегда содержит все члены базового класса.
Derived d = new Derived();
Base b = d; // Always OK.
Явные преобразования
Однако если преобразование не может быть выполнено без риска потери данных, для компилятора требуется, чтобы пользователь выполнил явное преобразование, которое называется приведением. Приведение является способом явно указать компилятору, что нужно сделать преобразование, и что известно, что может быть потеря данных. Для выполнения приведения заключите тип, в который производится приведение, в скобки перед преобразуемым значением или переменной. Следующая программа выполнят приведение типа doubledouble (справочник по C#) в тип intint (справочник по C#). Без приведения эта программа скомпилирована не будет.
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
Список разрешенных явных числовых преобразований, см. в разделе Таблица явных числовых преобразований (справочник по C#).
Для ссылочных типов явное приведение необходимо, если нужно выполнить преобразование из базового типа в производный тип:
// 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
// throw an exception at run time if the right-side
// object is not in fact a Giraffe.
Giraffe g2 = (Giraffe) a;
Операция приведения между ссылочными типами не меняет тип времени выполнения базового объекта; меняется только тип значения, которое используется в качестве ссылки на этот объект. Дополнительные сведения см. в разделе Полиморфизм (руководство по программированию в C#).
Исключения преобразования типов во время выполнения
В некоторых преобразованиях ссылочного типа компилятор не может определить, допустимо ли приведение. Для операции приведения возможна корректная ошибка компилятора во время выполнения. Как показано в следующем примере, приведение типов, которое заканчивается с ошибкой во время выполнения, вызывает InvalidCastException.
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.
System.Console.WriteLine("Press any key to exit.");
System.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 и as, чтобы можно было проверить совместимость перед действительным выполнением приведения. Дополнительные сведения см. в разделе Практическое руководство. Безопасное приведение с помощью операторов "as" и "is" (Руководство по программированию в C#).
Спецификация языка C#
Дополнительные сведения о приведении и о преобразованиях типов см. в следующих разделах документа Спецификация языка C#.
7.6.6 Выражения приведения
6.1 Неявные преобразования
6.2 Явные преобразования
См. также
Задачи
Основные понятия
Руководство по программированию в C#
Обобщенное преобразование типов
Преобразование экспортированного типа
Ссылки
Типы (руководство по программированию в C#)
Оператор () (Справочник по C#)
Операторы преобразования (Руководство по программированию в C#)
Журнал изменений
Дата |
Журнал изменений |
Причина |
---|---|---|
Июль 2008 |
Добавлено содержимое во введение и в некоторые другие разделы. |
Исправление ошибки содержимого. |