Kompilatorfel CS0029

Det går inte att implicit konvertera typen "type" till "type"

Kompilatorn kräver en explicit konvertering. Du kan till exempel behöva omvandla ett r-värde till samma typ som ett l-värde. Eller så måste du ange konverteringsrutiner för att stödja vissa överlagringar av operatören.

Konverteringar måste ske när du tilldelar en variabel av en typ till en variabel av en annan typ. När du gör en tilldelning mellan variabler av olika typer måste kompilatorn konvertera typen till höger om tilldelningsoperatorn till typen till vänster om tilldelningsoperatorn. Ta följande kod:

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

i = lng; gör en tilldelning, men datatyperna för variablerna till vänster och höger i tilldelningsoperatorn matchar inte. Innan du gör tilldelningen konverterar kompilatorn implicit variabeln lng, som är av typen long, till en int. Detta är implicit eftersom ingen kod uttryckligen instruerade kompilatorn att utföra den här konverteringen. Problemet med den här koden är att detta betraktas som en begränsad konvertering och kompilatorn tillåter inte implicita begränsade konverteringar eftersom det kan uppstå en potentiell dataförlust.

Det finns en begränsad konvertering när du konverterar till en datatyp som upptar mindre lagringsutrymme i minnet än den datatyp som vi konverterar från. Om du till exempel konverterar en lång till en int betraktas det som en begränsad konvertering. En lång tar upp 8 byte minne medan en int upptar 4 byte. Om du vill se hur dataförlust kan inträffa kan du överväga följande exempel:

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

Variabeln lng innehåller nu ett värde som inte kan lagras i variabeln i eftersom den är för stor. Om vi skulle konvertera det här värdet till en int-typ skulle vi förlora en del av våra data och det konverterade värdet skulle inte vara detsamma som värdet före konverteringen.

En bredare konvertering skulle vara motsatsen till en begränsad konvertering. Med bredare konverteringar konverterar vi till en datatyp som upptar mer lagringsutrymme i minnet än den datatyp vi konverterar från. Här är ett exempel på en bredare konvertering:

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

Observera skillnaden mellan det här kodexemplet och det första. Den här gången är variabeln lng till vänster om tilldelningsoperatorn, så det är målet för vår tilldelning. Innan tilldelningen kan göras måste kompilatorn implicit konvertera variabeln i, som är av typen int, för att skriva långt. Det här är en bredare konvertering eftersom vi konverterar från en typ som upptar 4 byte minne (en int) till en typ som upptar 8 byte minne (en lång). Implicita breddningskonverteringar tillåts eftersom det inte finns någon potentiell dataförlust. Alla värden som kan lagras i en int kan också lagras länge.

Vi vet att implicita begränsade konverteringar inte är tillåtna, så för att kunna kompilera den här koden måste vi uttryckligen konvertera datatypen. Explicita konverteringar görs med hjälp av gjutning. Casting är den term som används i C# för att beskriva konvertering av en datatyp till en annan. För att få koden att kompilera skulle vi behöva använda följande syntax:

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

Den tredje kodraden instruerar kompilatorn att explicit konvertera variabeln lng, som är av typen lång, till en int innan tilldelningen görs. Kom ihåg att med en begränsad konvertering kan data gå förlorade. Begränsade konverteringar bör användas med försiktighet och även om koden kompileras kan du få oväntade resultat vid körning.

Den här diskussionen har bara varit för värdetyper. När du arbetar med värdetyper arbetar du direkt med data som lagras i variabeln. .NET har dock också referenstyper. När du arbetar med referenstyper arbetar du med en referens till en variabel, inte faktiska data. Exempel på referenstyper skulle vara klasser, gränssnitt och matriser. Du kan inte implicit eller explicit konvertera en referenstyp till en annan om inte kompilatorn tillåter den specifika konverteringen eller lämpliga konverteringsoperatorer implementeras.

Följande exempel genererar 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
    }
}

Se även