C # 'da yanlış enum değeri [yineleme]
Aşağıdaki EOFçıktı neden çıktı olarak değil de yazdırılıyor ILLEGAL? EOF için başlatmayı NULL karaktere kaldırırsam, beklendiği gibi çalışır. Burada ne olduğunu anlayamıyor musunuz?
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
}
Yanıtlar
İlk olarak, bunun = '\0'ile aynı olduğunu unutmayın = 0. Bunun nedeni '\0', 0 sayısal değerine sahip olmasıdır. Numaranızın varsayılan temel türü vardır int. Sabit ifade '\0'dönüştürülür intarasında 0derleme zamanında.
İkinci olarak, dil spesifikasyonuna göre , numaralandırma üyelerinin yinelenen ilişkili değerlere sahip olabileceğini unutmayın.
Üçüncüsü, dil spesifikasyonunun aynı bölümünden,
Bir enum üyesinin ilişkili değeri örtülü veya açık olarak atanır. [...] Enum üyesinin bildiriminin başlatıcısı yoksa, ilişkili değeri aşağıdaki gibi örtük olarak ayarlanır:
Enum üyesi, enum türünde bildirilen ilk enum üyesi ise, ilişkili değeri sıfırdır.
Aksi takdirde, numaralandırma üyesinin ilişkili değeri, metin olarak önceki sıralama üyesinin ilişkili değeri bir artırılarak elde edilir. Bu artırılmış değer, temel alınan türle temsil edilebilecek değerler aralığı içinde olmalıdır, aksi takdirde bir derleme zamanı hatası oluşur.
Dolayısıyla, enum üyelerinizin ilişkili değerlerini açıkça yazarsam, şöyle olur:
public enum TokenType {
ILLEGAL = 0,
EOF = 0,
IDENT = 1,
INT = 2
};
ILLEGALve EOFaynı ilişkili değere sahip.
Dördüncü olarak, numaranızı Console.WriteLineçağırır ToString. Şimdi ne Enum.ToStringişe yaradığına bakın (Arayanlara Notlar bölümünde):
Birden çok numaralandırma üyesi aynı temel değere sahipse ve bir numaralandırma üyesinin adının dize temsilini temel değerine göre almaya çalışırsanız, kodunuz yöntemin hangi adla döneceği konusunda herhangi bir varsayımda bulunmamalıdır.
Bu nedenle, ILLEGAL"yöntemin hangi adla döneceği konusunda herhangi bir varsayımda bulunmamalısınız" için çıktı almak tamamen normaldir.
Başlatılıyor By EOF'0 \' ile değer bunu bir değer vermek 0.
Bunu bu örnekte görebilirsiniz:
Console.WriteLine(Convert.ToInt16(TokenType.EOF));
Console.WriteLine($"IntValue: {Convert.ToInt16('\0')}");
0
Toplam Değer: 0
Dahili olarak numaralandırma, tamsayılarda yukarı doğru sayarken 0'dan başlayarak değerler alır. Yüzeyin altında numaranız şöyle görünür:
public enum TokenType
{
ILLEGAL = 0,
EOF = 1
IDENT = 2,
INT = 3
};
Ama siz 0değer üzerinde a'yı zorlamayı seçtiniz EOF! Yani aynı değeri temsil eden 2 enum adınız var. Derleyici basitçe bulabildiği ilkini alır.
bu durumu açıklıyor
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', int türüne dönüştürüldüğünde 0 değerine yol açar. ve ilk değer olmayan başlatılmış enum bayrağı da 0 değerine sahiptir.