Berikut ini adalah pertanyaan wawancara. Saya datang dengan solusi, tetapi saya tidak yakin mengapa itu berhasil.
Pertanyaan:
Tanpa mengubah Sparta
kelas, tulis beberapa kode yang menghasilkan MakeItReturnFalse
return false
.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
Solusi saya: (SPOILER)
public class Place
{
public interface Sparta { }
}
Tapi kenapa Sparta
di MakeItReturnFalse()
rujuk {namespace}.Place.Sparta
bukan {namespace}.Sparta
?
c#
inheritance
types
namespaces
budi
sumber
sumber
Jawaban:
Pada dasarnya, karena itulah yang dikatakan oleh aturan pencarian nama. Dalam spesifikasi C # 5, aturan penamaan yang relevan ada di bagian 3.8 ("Namespace dan nama jenis").
Beberapa peluru pertama - terpotong dan diberi catatan - baca:
Jadi poin terakhir itulah yang mengambil
Sparta
kelas jika poin pertama tidak menemukan apa pun ... tetapi ketika kelas dasarPlace
mendefinisikan antarmukaSparta
, itu ditemukan sebelum kita mempertimbangkanSparta
kelas.Perhatikan bahwa jika Anda menjadikan tipe bertingkat
Place.Sparta
sebagai kelas daripada antarmuka, ia masih mengkompilasi dan mengembalikanfalse
- tetapi kompilator mengeluarkan peringatan karena tahu bahwa instance dariSparta
tidak akan pernah menjadi instance kelasPlace.Sparta
. Demikian juga jika Anda menyimpanPlace.Sparta
antarmuka tetapi membuatSparta
kelassealed
, Anda akan mendapatkan peringatan karena tidak adaSparta
instance yang dapat mengimplementasikan antarmuka tersebut.sumber
Sparta
kelas asli ,this is Place
kembalitrue
. Namun, menambahkanpublic interface Place { }
keSparta
kelas menyebabkanthis is Place
untuk kembalifalse
. Membuat kepalaku berputar.Place
sebagai antarmuka.Saat menentukan nama sesuai nilainya, "kedekatan" dari definisi tersebut digunakan untuk menyelesaikan ambiguitas. Definisi apapun yang "paling dekat" adalah definisi yang dipilih.
Antarmuka
Sparta
didefinisikan dalam kelas dasar. KelasSparta
didefinisikan dalam namespace yang memuat. Hal-hal yang didefinisikan dalam kelas dasar "lebih dekat" daripada hal-hal yang didefinisikan dalam namespace yang sama.sumber
Pertanyaan yang indah! Saya ingin menambahkan penjelasan yang sedikit lebih panjang untuk mereka yang tidak melakukan C # setiap hari ... karena pertanyaan ini merupakan pengingat yang baik tentang masalah resolusi nama secara umum.
Ambil kode aslinya, sedikit dimodifikasi dengan cara berikut:
return this is Sparta
).Athena
di filePlace
superclass untuk mengilustrasikan resolusi nama antarmuka.this
karena terikat diSparta
kelas, hanya untuk memperjelas semuanya.Kodenya terlihat seperti ini:
Kami sekarang membuat
Sparta
objek dan memanggil tiga metode.Output yang kami dapatkan adalah:
Namun, jika kita memodifikasi kelas Place dan mendefinisikan antarmuka Sparta:
maka inilah
Sparta
- antarmuka - yang akan tersedia terlebih dahulu untuk mekanisme pencarian nama dan keluaran kode kita akan berubah menjadi:Jadi kami secara efektif mengacaukan perbandingan tipe dalam
MakeItReturnFalse
definisi fungsi hanya dengan mendefinisikan antarmuka Sparta di superclass, yang ditemukan pertama kali oleh resolusi nama.Tetapi mengapa C # memilih untuk memprioritaskan antarmuka yang ditentukan dalam superclass dalam resolusi nama? @JonSet tahu! Dan jika Anda membaca jawabannya, Anda akan mendapatkan detail dari protokol resolusi nama di C #.
sumber