CS0029 fordítási hiba

A típus nem konvertálható implicit módon "típussá"

A fordító explicit átalakítást igényel. Előfordulhat például, hogy az r-értéknek ugyanolyan típusúnak kell lennie, mint az l-érték. Vagy meg kell adnia a konverziós rutinokat bizonyos operátorok túlterhelésének támogatásához.

A konvertálásnak akkor kell történnie, ha egy változó egy másik típusú változóhoz rendel hozzá egy másik típusú változót. Ha különböző típusú változók közötti hozzárendelést végez, a fordítónak a hozzárendelési operátor jobb oldalán lévő típust a hozzárendelési operátor bal oldalán lévő típussá kell alakítania. Kövesse a következő kódot:

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

i = lng; hozzárendelést végez, de a hozzárendelés-operátor bal és jobb oldalán lévő változók adattípusai nem egyeznek. A hozzárendelés elvégzése előtt a fordító implicit módon konvertálja a változót lng, amely hosszú típusú, int értékké. Ez implicit, mert egyetlen kód sem utasította explicit módon a fordítót a konvertálás végrehajtására. A kóddal az a probléma, hogy ez szűkítő konverziónak minősül, és a fordító nem teszi lehetővé az implicit szűkítési konverziókat, mert lehetséges adatvesztés lehet.

Szűkítő átalakítás akkor létezik, ha olyan adattípusra konvertál, amely kevesebb tárterületet foglal el a memóriában, mint a konvertálni kívánt adattípus. A hosszúak intre konvertálása például szűkülő átalakításnak minősül. A hosszúak 8 bájt memóriát foglalnak el, míg egy int 4 bájtot foglal el. Az adatvesztés előfordulásának megtekintéséhez tekintse meg az alábbi mintát:

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

A változó lng most olyan értéket tartalmaz, amely nem tárolható a változóban i , mert túl nagy. Ha ezt az értéket int típussá konvertálnánk, elveszítenénk néhány adatunkat, és az átalakított érték nem lenne ugyanaz, mint az átalakítás előtti érték.

A szélesítő átalakítás a szűkülő átalakítás ellentéte lenne. Az átalakítások szélesítésével olyan adattípussá alakítunk át, amely több tárterületet foglal el a memóriában, mint a konvertálni kívánt adattípus. Íme egy példa a szélesebb körű átalakításra:

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

Figyelje meg a kódminta és az első közötti különbséget. A változó lng ezúttal a hozzárendelés-operátor bal oldalán található, ezért a hozzárendelés célja. A hozzárendelés végrehajtása előtt a fordítónak implicit módon hosszúra kell konvertálnia a változót i, amely int típusú. Ez egy kibővítő átalakítás, mivel egy 4 bájt memóriát (int) tartalmazó típusról 8 bájt memóriát (hosszú) elfoglaló típusra konvertálunk. Az implicit szélesítési konverziók azért engedélyezettek, mert nincs lehetséges adatvesztés. Minden intben tárolható érték hosszú ideig is tárolható.

Tudjuk, hogy az implicit szűkítő konverziók nem engedélyezettek, ezért ahhoz, hogy lefordíthassuk ezt a kódot, explicit módon konvertálnunk kell az adattípust. Az explicit átalakítások a casting használatával végezhetők el. A casting a C#-ban használt kifejezés az egyik adattípus egy másikra való konvertálásának leírására. A lefordítandó kód lekéréséhez a következő szintaxist kell használnunk:

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

A harmadik kódsor arra utasítja a fordítót, hogy a hozzárendelés előtt explicit módon konvertálja a hosszú típusú változót lngegy intre. Ne feledje, hogy szűkülő átalakítás esetén lehetséges adatvesztés. A konverziók szűkítését körültekintően kell használni, és bár a kód lefordítja, futásidőben váratlan eredményeket kaphat.

Ez a vita csak értéktípusokra vonatkozik. Az értéktípusok használatakor közvetlenül a változóban tárolt adatokkal dolgozik. A .NET azonban referenciatípusokkal is rendelkezik. A referenciatípusok használatakor egy változóra mutató hivatkozással dolgozik, nem pedig a tényleges adatokkal. Ilyenek például az osztályok, interfészek és tömbök. Nem konvertálhat implicit módon vagy explicit módon egy referenciatípust egy másikra, kivéve, ha a fordító engedélyezi az adott átalakítást, vagy a megfelelő konverziós operátorok implementálva vannak.

Az alábbi minta a CS0029-et hozza létre:

// 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
    }
}

Lásd még