Ошибка компилятора CS0029

Не удается неявно преобразовать тип "type" в "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. Это будет расширяющее преобразование, поскольку исходный тип (int) занимает в памяти 4 байта, а целевой (long) — 8 байт. Неявные расширяющие преобразования не связаны с риском потери данных и допускаются к применению. Любое значение типа int может быть сохранено в переменной типа long.

Поскольку неявные сужающие преобразования не допускаются, для успешной компиляции этого кода необходимо явно выполнить преобразование типа данных. Явные преобразования выполняются путем приведения типов. Понятие приведения типов в языке C# описывает преобразование одного типа в другой. Чтобы гарантировать успешную компиляцию кода, необходимо использовать следующий синтаксис:

int i = 50;
long lng = 100;
i = (int) lng;   // Cast to int.

В третьей строке кода содержится инструкция для явного преобразования переменной lng типа long в тип int перед выполнением присвоения. Помните, что при сужающем преобразовании существует риск потери данных. Сужающие преобразования следует использовать с осторожностью, поскольку даже в случае успешной компиляции кода во время выполнения могут быть получены непредвиденные результаты.

Приведенная здесь информация относится только к типам значений. При использовании типов значений вы работаете напрямую с данными, хранящимися в переменной. Но в .NET также есть ссылочные типы. В случае с ними вы работаете не с фактическими данными, а со ссылками на переменные. Например, к ссылочным типам относятся классы, интерфейсы и массивы. Неявные или явные преобразования между ссылочными типами не поддерживаются кроме случаев, когда компилятор допускает конкретные преобразования или реализованы соответствующие операторы преобразования.

В следующем примере возникает ошибка 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()
    {
        var myInt = new MyInt();
        int i = myInt; // CS0029
    }
}

См. также