Szél Péter

Mi történik akkor, ha egy olyan egész számot szeretnénk enum típusúvá castolni, amely nem is volt definiálva az adott enumban? Arra számítok, hogy futás idejű hibát kapok, ehelyett meglepő dolog történik.

Nézzük az alábbi példát:

enum Permission  
{
    Read = 1,
    Write = 2,
    Execute = 3
}

void Main()  
{
    var permission = (Permission)5;
    int another = (int)permission;

    Console.WriteLine(permission);
}

Világos, hogy az 5-ös érték nem definiált az enumban, hibás működést fogunk kapni, de nem keletkezik kivétel, a program minden hiba nélkül lefut és kiírja, hogy 5.

A .NET környezetben többek között azt szeretjük, hogy típusbiztos, így megkímél olyan hibáktól, amelyek során inkompatibilis műveleteket végeznénk az adott objektumon. Ehhez képest az Enumomat teljesen boldogan beengedte olyan állapotba, amely nem is definiált. Az eredmény megértéséhez nézzük a motorháztető alá, itt az adott rész IL reprezentációja:

IL_0001:  ldc.i4.5  
IL_0002:  stloc.0     // permission  
IL_0003:  ldloc.0     // permission  
IL_0004:  stloc.1     // another  

Az eredmény meglepő, IL szinten egyáltalán nem jelenik meg az Enumunk se a castolás, olyan, mintha végig int-tel dolgoztunk volna. Ha leveszem a castolásokat:

void Main()  
{
    int permission = 5;
    int another = permission;
}
IL_0001:  ldc.i4.5  
IL_0002:  stloc.0     // permission  
IL_0003:  ldloc.0     // permission  
IL_0004:  stloc.1     // another  

Az eredmény tökéletesen ugyan az.

A tanulság az, hogy külső helyről származó int castolása előtt mindig le kell ellenőrizni, hogy van-e egyáltalán ilyen érték definiálva:

int input = 5;  
if(!Enum.IsDefined(typeof(Permission), input))  
    throw new InvalidOperationException("Input value not defined in Permission enum. Value: " + input);

var permission = (Permission)input;  

Az Enum tehát valójában csak egy C# szimbólum, amely sokat dob a kód olvashatóságán, azonban a motorháztető alatt csak egy egész típus, semmilyen védelmet nem nyújt a keretrendszer a hibás használattal szemben.

Tetszett az írásom? Akkor oszd meg az alábbi gombok használatával! :)