Karena bug yang diperbaiki di C # 4, program berikut dicetak true
. (Cobalah di LINQPad)
void Main() { new Derived(); }
class Base {
public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); }
}
class Derived : Base {
string CheckNull() { return "Am I null? " + (this == null); }
public Derived() : base(() => CheckNull()) { }
}
Dalam VS2008 dalam mode Rilis, ia melempar InvalidProgramException. (Dalam mode Debug, itu berfungsi dengan baik)
Dalam VS2010 Beta 2, itu tidak dikompilasi (saya tidak mencoba Beta 1); Saya mempelajarinya secara susah-payah
Apakah ada cara lain untuk membuat this == null
C # murni?
Jawaban:
Pengamatan ini telah diposting di StackOverflow di pertanyaan lain sebelumnya hari ini.
Marc 's jawaban yang bagus untuk pertanyaan itu menunjukkan bahwa menurut spec (bagian 7.5.7), Anda tidak harus dapat akses
this
dalam konteks dan kemampuan untuk melakukannya di C # 3.0 compiler bug. Kompiler C # 4.0 berperilaku benar sesuai dengan spesifikasi (bahkan dalam Beta 1, ini adalah kesalahan waktu kompilasi):sumber
: base(CheckNull())
jika CheckNull tidak statis, dan Anda juga seharusnya tidak dapat menyejajarkan lambda yang terhubung dengan instance.this
dalamCheckNull
metode legal Apa yang tidak legal adalah implisit ini-akses di() => CheckNull()
, pada dasarnya() => this.CheckNull()
, yang berjalan di luar blok dari sebuah contoh konstruktor. Saya setuju bahwa bagian dari spesifikasi yang saya kutip sebagian besar terfokus pada legalitas sintaksisthis
kata kunci, dan mungkin bagian lain membahas masalah ini dengan lebih tepat, tetapi mudah untuk secara ekstrapolasi secara konseptual dari bagian spesifikasi ini juga.Dekompilasi mentah (Reflektor tanpa optimasi) dari biner mode Debug adalah:
Metode CompilerGenerated tidak masuk akal; jika Anda melihat IL (di bawah), itu memanggil metode pada string nol (!).
Dalam mode Rilis, variabel lokal dioptimalkan menjauh, sehingga mencoba untuk mendorong variabel yang tidak ada ke stack.
(Reflektor lumpuh saat mengubahnya menjadi C #)
EDIT : Apakah ada orang (Eric Lippert?) Yang tahu mengapa kompiler memancarkan
ldloc
?sumber
Saya sudah memilikinya! (dan mendapat bukti juga)
sumber
Ini bukan "bug". Ini adalah Anda menyalahgunakan sistem tipe. Anda seharusnya tidak pernah memberikan referensi ke instance saat ini (
this
) kepada siapa pun dalam konstruktor.Saya bisa membuat "bug" serupa dengan memanggil metode virtual di dalam konstruktor kelas dasar juga.
Hanya karena Anda dapat melakukan sesuatu yang buruk tidak berarti itu bug ketika Anda mendapatkannya sedikit.
sumber
InvalidProgramException
.Saya bisa saja salah, tapi saya cukup yakin jika objek Anda
null
tidak akan ada skenario di manathis
berlaku.Misalnya, bagaimana Anda menelepon
CheckNull
?sumber
this
yang saling eksklusif dari kemungkinan menjadi null - semacam "Cogito, ergo sum" pemrograman komputer. Oleh karena itu keinginan Anda untuk menggunakan ekspresithis == null
dan mengembalikannya benar menurut saya sebagai salah arah.Tidak yakin apakah ini yang Anda cari
contoh: UserID = CheckForNull (Request.QueryString ["UserID"], 147);
sumber