valeur d'énumération incorrecte en C # [duplicate]
Pourquoi l'impression suivante EOFest-elle la sortie et non ILLEGAL? Si je supprime l'initialisation pour EOF au caractère NULL, cela fonctionne comme prévu. Vous ne comprenez pas ce qui se passe ici?
public enum TokenType {
ILLEGAL,
EOF= '\0',//remove the initialization to have it work as expected
IDENT,
INT
};
void Main()
{
Console.WriteLine(TokenType.ILLEGAL);//Prints EOF. Should have printed ILLEGAL
}
Réponses
Tout d'abord, notez que = '\0'c'est la même chose que = 0. Cela est dû au '\0'fait que la valeur numérique est 0. Votre énumération a le type sous-jacent par défaut de int. L'expression constante '\0'est convertie en intde 0au moment de la compilation.
Deuxièmement, selon la spécification du langage , notez que les membres enum peuvent avoir des valeurs associées dupliquées.
Troisièmement, à partir de la même section de la spécification de langue,
La valeur associée d'un membre enum est affectée implicitement ou explicitement. [...] Si la déclaration du membre enum n'a pas d'initialiseur, sa valeur associée est définie implicitement, comme suit:
Si le membre enum est le premier membre enum déclaré dans le type enum, sa valeur associée est zéro.
Sinon, la valeur associée du membre enum est obtenue en augmentant la valeur associée du membre enum précédent textuellement de un. Cette valeur accrue doit être comprise dans la plage de valeurs pouvant être représentées par le type sous-jacent, sinon une erreur de compilation se produit.
Donc, si je devais écrire explicitement les valeurs associées aux membres de votre enum, ce serait:
public enum TokenType {
ILLEGAL = 0,
EOF = 0,
IDENT = 1,
INT = 2
};
ILLEGALet EOFont la même valeur associée.
Quatrièmement, Console.WriteLineappelle ToStringvotre énumération. Maintenant, regardez ce que Enum.ToStringfait (dans la section Notes aux appelants):
Si plusieurs membres d'énumération ont la même valeur sous-jacente et que vous essayez de récupérer la représentation sous forme de chaîne du nom d'un membre d'énumération en fonction de sa valeur sous-jacente, votre code ne doit faire aucune hypothèse sur le nom que la méthode retournera.
Donc, la sortie ILLEGALest tout à fait normale, car vous "ne devriez pas faire d'hypothèses sur le nom que la méthode retournera".
En initialisant la EOFvaleur avec '\ 0', vous lui donnez la valeur 0.
Vous pouvez le voir dans cet exemple:
Console.WriteLine(Convert.ToInt16(TokenType.EOF));
Console.WriteLine($"IntValue: {Convert.ToInt16('\0')}");
0
IntValue: 0
En interne, l'énumération obtiendra des valeurs à partir de 0 en comptant vers le haut en nombres entiers. Donc, sous la surface, votre énumération ressemble à ceci:
public enum TokenType
{
ILLEGAL = 0,
EOF = 1
IDENT = 2,
INT = 3
};
Mais vous avez choisi d'appliquer un 0sur la valeur EOF! Vous avez donc 2 noms d'énumérations représentant la même valeur. Le compilateur prend simplement le premier qu'il peut trouver.
ceci explique la siutation
foreach (Enum e in Enum.GetValues(typeof(TokenType)))
Console.WriteLine("{0}: {1}", e, Convert.ToInt16(e));
Console.WriteLine();
foreach (Enum e in Enum.GetValues(typeof(Another_TokenType)))
Console.WriteLine("{0}: {1}", e, Convert.ToInt16(e));
EOF: 0
EOF: 0
IDENT: 1
INT: 2
ILLEGAL: 0
ILLEGAL: 0
EOF: 1
IDENT: 2
'\ 0' conduit à la valeur 0 lorsqu'il est converti en int. et le premier indicateur d'énumération initialisé sans valeur a également la valeur 0.