Compiler Error CS0029

Cannot implicitly convert type 'type' to 'type'

The compiler requires an explicit conversion. For example, you may need to cast an r-value to be the same type as an l-value. Or, you must provide conversion routines to support certain operator overloads.

Conversions must occur when assigning a variable of one type to a variable of a different type. When making an assignment between variables of different types, the compiler must convert the type on the right-hand side of the assignment operator to the type on the left-hand side of the assignment operator. Take the following the code:

int i = 50;
long lng = 100;
i = lng;

i = lng; makes an assignment, but the data types of the variables on the left and right-hand side of the assignment operator don't match. Before making the assignment the compiler is implicitly converting the variable lng, which is of type long, to an int. This is implicit because no code explicitly instructed the compiler to perform this conversion. The problem with this code is that this is considered a narrowing conversion, and the compiler does not allow implicit narrowing conversions because there could be a potential loss of data.

A narrowing conversion exists when converting to a data type that occupies less storage space in memory than the data type we are converting from. For example, converting a long to an int would be considered a narrowing conversion. A long occupies 8 bytes of memory while an int occupies 4 bytes. To see how data loss can occur, consider the following sample:

int i = 50;
long lng = 3147483647;
i = lng;

The variable lng now contains a value that cannot be stored in the variable i because it is too large. If we were to convert this value to an int type we would be losing some of our data and the converted value would not be the same as the value before the conversion.

A widening conversion would be the opposite of a narrowing conversion. With widening conversions, we are converting to a data type that occupies more storage space in memory than the data type we are converting from. Here is an example of a widening conversion:

int i = 50;
long lng = 100;
lng = i;

Notice the difference between this code sample and the first. This time the variable lng is on the left-hand side of the assignment operator, so it is the target of our assignment. Before the assignment can be made, the compiler must implicitly convert the variable i, which is of type int, to type long. This is a widening conversion since we are converting from a type that occupies 4 bytes of memory (an int) to a type that occupies 8 bytes of memory (a long). Implicit widening conversions are allowed because there is no potential loss of data. Any value that can be stored in an int can also be stored in a long.

We know that implicit narrowing conversions are not allowed, so to be able to compile this code we need to explicitly convert the data type. Explicit conversions are done using casting. Casting is the term used in C# to describe converting one data type to another. To get the code to compile we would need to use the following syntax:

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

The third line of code tells the compiler to explicitly convert the variable lng, which is of type long, to an int before making the assignment. Remember that with a narrowing conversion, there is a potential loss of data. Narrowing conversions should be used with caution and even though the code will compile you may get unexpected results at run-time.

This discussion has only been for value types. When working with value types you work directly with the data stored in the variable. However, the .NET Framework also has reference types. When working with reference types you are working with a reference to a variable, not the actual data. Examples of reference types would be classes, interfaces and arrays. You cannot implicitly or explicitly convert one reference type to another unless the compiler allows the specific conversion or the appropriate conversion operators are implemented.

The following sample generates 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
   }
}

See Also

Reference

Conversion Operators (C# Programming Guide)