Mengapa kode ini berfungsi? Saya menggunakan C # 8 dengan Visual Studio 2019.
Anda telah menjawab pertanyaan Anda sendiri! Itu karena Anda menggunakan C # 8.
Aturan dari C # 1 hingga 7 adalah: nama sederhana tidak dapat digunakan untuk mengartikan dua hal yang berbeda dalam lingkup lokal yang sama. (Aturan sebenarnya sedikit lebih kompleks dari itu tetapi menggambarkan bagaimana itu membosankan; lihat spesifikasi C # untuk detailnya.)
Maksud aturan ini adalah untuk mencegah situasi yang sedang Anda bicarakan dalam contoh Anda, di mana menjadi sangat mudah untuk dibingungkan tentang arti lokal. Secara khusus, aturan ini dirancang untuk mencegah kebingungan seperti:
class C
{
int x;
void M()
{
x = 123;
if (whatever)
{
int x = 356;
...
Dan sekarang kita memiliki situasi di mana di dalam tubuh M
, x
berarti keduanya this.x
dan lokal x
.
Meskipun bermaksud baik, ada sejumlah masalah dengan aturan ini:
- Itu tidak diterapkan untuk spec. Ada situasi di mana nama sederhana dapat digunakan sebagai, katakanlah, baik tipe dan properti, tetapi ini tidak selalu ditandai sebagai kesalahan karena logika deteksi kesalahan cacat. (Lihat di bawah)
- Pesan-pesan kesalahan itu membingungkan, dan dilaporkan secara tidak konsisten. Ada beberapa pesan kesalahan yang berbeda untuk situasi ini. Mereka secara tidak konsisten mengidentifikasi pelaku; yaitu, kadang-kadang penggunaan batin akan dipanggil, kadang-kadang luar , dan kadang-kadang hanya membingungkan.
Saya berusaha keras dalam menulis ulang Roslyn untuk menyelesaikan masalah ini; Saya menambahkan beberapa pesan kesalahan baru, dan membuat yang lama konsisten mengenai di mana kesalahan itu dilaporkan. Namun, upaya ini terlalu sedikit, sudah terlambat.
Tim C # memutuskan untuk C # 8 bahwa seluruh aturan menyebabkan lebih banyak kebingungan daripada yang mencegahnya, dan aturan tersebut dipensiunkan dari bahasa. (Terima kasih Jonathon Chase untuk menentukan kapan pensiun terjadi.)
Jika Anda tertarik untuk mempelajari sejarah masalah ini dan bagaimana saya berusaha memperbaikinya, lihat artikel yang saya tulis tentang ini:
https://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/
https://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/
https://ericlippert.com/2014/09/25/confusing-errors-for-a-confusing-feature-part-one/
https://ericlippert.com/2014/09/29/confusing-errors-for-a-confusing-feature-part-two/
https://ericlippert.com/2014/10/03/confusing-errors-for-a-confusing-feature-part-three/
Pada akhir bagian tiga saya mencatat bahwa ada juga interaksi antara fitur ini dan fitur "Warna Warna" - yaitu, fitur yang memungkinkan:
class C
{
Color Color { get; set; }
void M()
{
Color = Color.Red;
}
}
Di sini kita telah menggunakan nama sederhana Color
untuk merujuk pada keduanya this.Color
dan jenis yang disebutkan Color
; menurut pembacaan yang ketat dari spesifikasi ini harus menjadi kesalahan, tetapi dalam kasus ini spesifikasi itu salah dan niat untuk memperbolehkannya, karena kode ini tidak ambigu dan akan membingungkan untuk membuat pengembang mengubahnya.
Saya tidak pernah menulis artikel yang menggambarkan semua interaksi aneh antara kedua aturan ini, dan itu akan menjadi sedikit sia-sia untuk melakukannya sekarang!
x
parameter untuk metode itu akan dipindahkan dari ruang lingkup. Lihat sharplab untuk contohnya.