salah nilai enum di C # [duplikat]

Sep 09 2020

Mengapa pencetakan berikut EOFsebagai keluaran dan bukan ILLEGAL? Jika saya menghapus inisialisasi untuk karakter EOF ke NULL, itu berfungsi seperti yang diharapkan. Tidak mengerti apa yang terjadi di sini?

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
}

Jawaban

4 Sweeper Sep 09 2020 at 07:06

Pertama, perhatikan bahwa = '\0'itu sama dengan = 0. Ini karena '\0'memiliki nilai numerik 0. Enum Anda memiliki tipe dasar default int. Ekspresi konstanta '\0'diubah menjadi intdari 0pada waktu kompilasi.

Kedua, sesuai spesifikasi bahasa , perhatikan bahwa anggota enum dapat memiliki duplikat nilai terkait.

Ketiga, dari bagian spesifikasi bahasa yang sama,

Nilai terkait dari anggota enum ditetapkan baik secara implisit maupun eksplisit. [...] Jika deklarasi anggota enum tidak memiliki penginisialisasi, nilai yang terkait ditetapkan secara implisit, sebagai berikut:

  • Jika anggota enum adalah anggota enum pertama yang dideklarasikan dalam jenis enum, nilainya yang terkait adalah nol.

  • Jika tidak, nilai terkait anggota enum diperoleh dengan meningkatkan nilai terkait anggota enum sebelumnya secara tekstual sebesar satu. Nilai yang meningkat ini harus berada dalam kisaran nilai yang dapat diwakili oleh tipe yang mendasarinya, jika tidak, kesalahan waktu kompilasi akan terjadi.

Jadi jika saya menulis nilai terkait anggota enum Anda secara eksplisit, itu adalah:

public enum TokenType {
        ILLEGAL = 0,
        EOF = 0,
        IDENT = 1,
        INT = 2
        };

ILLEGALdan EOFmemiliki nilai terkait yang sama.

Keempat, Console.WriteLinememanggil ToStringenum Anda. Sekarang lihat apa Enum.ToStringfungsinya (di bagian Catatan untuk Penelepon):

Jika beberapa anggota enumerasi memiliki nilai dasar yang sama dan Anda mencoba mengambil representasi string dari nama anggota enumerasi berdasarkan nilai yang mendasarinya, kode Anda tidak boleh membuat asumsi apa pun tentang nama mana yang akan dikembalikan oleh metode.

Jadi, keluarannya ILLEGALbenar-benar normal, karena Anda "tidak boleh membuat asumsi tentang nama mana yang akan dikembalikan metode".

5 MongZhu Sep 09 2020 at 06:52

Dengan menginisialisasi EOFnilai dengan '\ 0' Anda memberinya nilai 0.

Anda dapat melihat ini di contoh ini:

Console.WriteLine(Convert.ToInt16(TokenType.EOF));
Console.WriteLine($"IntValue: {Convert.ToInt16('\0')}");

0
IntValue: 0

Secara internal, enum akan mendapatkan nilai mulai dari 0 saat menghitung ke atas dalam bilangan bulat. Jadi di bawah permukaan enum Anda terlihat seperti ini:

public enum TokenType
{
    ILLEGAL = 0,
    EOF = 1
    IDENT = 2,
    INT = 3
};

Tapi Anda memilih untuk memaksakan 0nilai EOF! Jadi, Anda memiliki 2 nama enum yang mewakili nilai yang sama. Kompiler hanya mengambil yang pertama yang dapat ditemukannya.

1 DervişKayımbaşıoğlu Sep 09 2020 at 07:01

ini menjelaskan 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' mengarah ke nilai 0 jika dikonversi ke int. dan flag enum yang diinisialisasi bukan nilai pertama juga bernilai 0.