Ошибка компилятора CS0029
Обновлен: Ноябрь 2007
Сообщение об ошибке
Невозможно неявным образом преобразовать тип "тип" в "тип"
Cannot implicitly convert type 'type' to 'type'
Компилятору необходимо выполнить явное преобразование. Например, может возникнуть необходимость привести r-значение к тому же типу, что имеет l-значение. Или необходимо предоставить процедуры преобразования для поддержки перегрузки определенных операторов.
При назначении переменной одного типа переменной другого типа потребуется преобразование. При выполнении назначений между различными типами компилятор должен преобразовать тип справа от оператора назначения типу слева от оператора назначения. Возьмем следующий код.
int i = 50;
long lng = 100;
i = lng;
i = lng; выполняется назначение, но типы данных переменных слева и справа от оператора назначения не совпадают. Прежде чем выполнить назначение, компилятор неявно преобразовывает переменную lng типа long в тип int. Это делается неявно, так как никакой код явным образом не указывает компилятору выполнять такое преобразование. Проблема в этом коде заключается в том, что это считается сужающим преобразованием, а компилятор не допускает неявных сужающих преобразований, поскольку это может привести к потенциальной потере данных.
Сужающее преобразование существует при преобразовании в тип данных, занимающий меньше пространства в памяти, чем тип из которого выполняется преобразование. Например, преобразование long в int будет считаться сужающим преобразованием. Тип long занимает 8 байт памяти, в то время как тип int – 4 байта. То, как происходит потеря данных, можно увидеть в следующем примере:
int i = 50;
long lng = 3147483647;
i = lng;
Теперь переменная lng содержит значение, которое не может храниться в переменной i, так как оно слишком большое. Если бы мы преобразовали это в тип int, то потеряли бы часть данные, и преобразованное значение не было бы таким же, как до преобразования.
Расширяющее преобразование противопоставляется сужающему преобразованию. При расширяющем преобразовании выполняется преобразование в тип данных, занимающий больше пространства в памяти, чем тип из которого выполняется преобразование. Ниже приведет пример расширяющего преобразования.
int i = 50;
long lng = 100;
lng = i;
Обратите внимание на разницу между этим примером кода и первым примером. Когда переменная lng расположена слева от оператора назначения, она является целью назначения. Прежде чем будет выполнено назначение, компилятор должен неявно преобразовать переменную i типа int в тип long. Выполняется расширяющее преобразование, так как тип, занимающий 4 байта памяти (int) преобразуется в тип, занимающий 8 байт памяти (long). Неявное расширяющее преобразование допускается, так как проблемы потенциальной потери данных не существует. Любое значение, которое может храниться в типе int, может хранится и в типе long.
Как известно, неявное сужающее преобразование не разрешено, поэтому для компиляции этого кода потребуется явное преобразование типа данных. Явное преобразование выполняется путем приведения. Термин "приведение" используется для языке C# для описания преобразования одного типа данных в другой. Чтобы получить код для компиляции, необходимо использовать следующий синтаксис.
int i = 50;
long lng = 100;
i = (int) lng; // cast to int
Третья строка кода заставляет компилятор явно преобразовать переменную lng, имеющую тип long, в тип int перед выполнением приведения. Помните, что при сужающем преобразовании возникает потенциальная потеря данных. Сужающее преобразование следует использовать с осторожностью, и даже если код будет скомпилирован, результаты во время выполнения могут оказать непредвиденными.
В этом разделе описаны только типы значений. При работе с типами значений непосредственно используются данные, хранящиеся в переменной. Однако в платформе .NET Framework также имеются ссылочные типы. При работе со ссылочными типами используется ссылка на переменную, а не фактически данные. Примерами ссылочных типов являются классы, интерфейсы и массивы. Явно или неявно преобразовать один ссылочный тип в другой невозможно, если только компилятор не допускает особого преобразования или если не реализованы соответствующие операторы преобразования.
Следующий пример приводит к возникновению ошибки CS0029:
// CS0029.cs
public class MyInt
{
private int x = 0;
// Uncomment this conversion routine to resolve CS0029
/*
public static implicit operator int(MyInt i)
{
return i.x;
}
*/
public static void Main()
{
MyInt myInt = new MyInt();
int i = myInt; // CS0029
}
}
См. также
Ссылки
Операторы преобразования (Руководство по программированию в C#)