Warning : This page has been marked as an archive because the author consider that its content is no longer relevant.

Récemment je suis tombé sur un cast qui a éveillé ma curiosité.

La ligne tentait de convertir un entier en une énumération d’une manière que je n’avais jamais vu.

Soit le type d’énumération suivant :

public enum MyEnum
{
    Zero = 0,
    One = 1
}

Soit le cast suivant :

MyEnum res;
int val = 1;

res = (MyEnum)Enum.Parse(typeof(MyEnum), val.ToString());

La première réaction que j’ai eu a été de me demander pourquoi diable convertir un entier en string pour le caster en énumération juste après quand un cast direct suffit ?

res = (MyEnum)val;

J’ai donc posé la question à un collègue en me demandant si j’avais pas raté un truc et on m’a répondu que Enum.Parse renvoie une exception si la variable val a une valeur ne correspondant pas aux valeurs possibles déclarées de l’énumération (par exemple 2).

Deuxième moment de doute. Je me décide donc à faire un petit test :

// Cast 1
res = (MyEnum)Enum.ToObject(typeof(MyEnum), val);
Console.Out.WriteLine("{0}", res);
    
// Cast 2
res = (MyEnum)Enum.Parse(typeof(MyEnum), val.ToString(CultureInfo.InvariantCulture));
Console.Out.WriteLine("{0}", res);
    
// Cast 3
res = (MyEnum)val;
Console.Out.WriteLine("{0}", res);

J’ai pu constater qu’avec ces tests toutes les conversions passaient avec val valant 2. Aucune exceptions ou erreurs de lancée. Celà veux donc dire que la valeur numérique de res est ici de deux alors que la valeur maximum déclarée est de 1 ! Ce comportement ressemble étrangement au C.

Maintenant que se passe-t-il avec le test suivant :

// Cast 4
string sVal = "Two";
res = (MyEnum)Enum.Parse(typeof(MyEnum), sVal);
Console.Out.WriteLine("{0}", res);

Cette fois-ci nous avons bien une exception de lancée indiquant que la valeur Two n’existe pas dans l’énumération ce qui est un comportement attendu.

Si on reviens à la ligne qui m’as posé problème au début de l’article on se rend donc compte de l’erreur du développeur pensant que Enum.Parse fonctionne de la manière avec des chaînes qu’avec des chaînes contenant une valeur numérique entière.

Dès lors comment s’assurer que la valeur que nous souhaitons convertir dans l’énumération existe belle et bien ?

Plusieurs choix s’offrent à nous :

if (typeof(MyEnum).IsEnumDefined(val))
{
    res = (MyEnum)val;
    Console.Out.WriteLine("{0}", res);
}
else
    Console.Out.WriteLine("Cannot convert {0} to MyEnum", val);
            
if (Enum.IsDefined(typeof(MyEnum), val))
{
    res = (MyEnum) val;
    Console.Out.WriteLine("{0}", res);
}
else
    Console.Out.WriteLine("Cannot convert {0} to MyEnum", val);

La première méthode n’existe qu’à partir de .NET 4 alors que la seconde existe dans les précédentes versions du framework.

Comme quoi on peux en apprendre tout les jours sur notre langage préféré.

Et vous ? Le saviez-vous ?

Comments