Aufgrund eines Fehlers, der in C # 4 behoben wurde, wird das folgende Programm gedruckt true
. (Probieren Sie es in 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()) { }
}
In VS2008 im Release-Modus wird eine InvalidProgramException ausgelöst. (Im Debug-Modus funktioniert es gut)
In VS2010 Beta 2 wird es nicht kompiliert (ich habe Beta 1 nicht ausprobiert). Das habe ich auf die harte Tour gelernt
Gibt es eine andere Möglichkeit, this == null
reines C # zu erstellen?
Antworten:
Diese Beobachtung wurde heute in einer anderen Frage auf StackOverflow veröffentlicht .
Marc ' gute Antwort auf diese Frage zeigt, dass Sie gemäß der Spezifikation (Abschnitt 7.5.7)
this
in diesem Kontext nicht zugreifen können sollten und die Möglichkeit, dies im C # 3.0-Compiler zu tun, ein Fehler ist. Der C # 4.0-Compiler verhält sich gemäß der Spezifikation korrekt (selbst in Beta 1 ist dies ein Fehler bei der Kompilierung):quelle
: base(CheckNull())
wenn CheckNull nicht statisch ist, und Sie sollten auch nicht in der Lage sein, ein instanzgebundenes Lambda zu inline.this
inCheckNull
Methode ist legal. Was nicht legal ist, ist der implizite Zugriff auf diesen Zugriff im() => CheckNull()
Wesentlichen() => this.CheckNull()
, der außerhalb des Blocks eines Instanzkonstruktors ausgeführt wird. Ich bin damit einverstanden, dass sich der von mir zitierte Teil der Spezifikation hauptsächlich auf die syntaktische Rechtmäßigkeit vonthis
Schlüsselwörtern konzentriert, und wahrscheinlich befasst sich ein anderer Teil genauer mit diesem Problem, aber es ist auch einfach, konzeptionell aus diesem Teil der Spezifikation zu extrapolieren.Die Rohdekompilierung (Reflektor ohne Optimierungen) der Binärdatei im Debug-Modus lautet:
Die CompilerGenerated-Methode ist nicht sinnvoll. wenn man sich die IL (unten) aussehen, es ruft die Methode auf einem Null - Zeichenfolge (!).
Im Freigabemodus wird die lokale Variable weg optimiert, sodass versucht wird, eine nicht vorhandene Variable auf den Stapel zu verschieben.
(Der Reflektor stürzt ab, wenn er in C # umgewandelt wird.)
EDIT : Weiß jemand (Eric Lippert?), Warum der Compiler das ausgibt
ldloc
?quelle
Ich habe das gehabt! (und bekam auch Beweise)
quelle
Dies ist kein "Bug". Dies ist, dass Sie das Typsystem missbrauchen. Sie sollten niemals einen Verweis auf die aktuelle Instanz (
this
) an jemanden innerhalb eines Konstruktors übergeben.Ich könnte einen ähnlichen "Fehler" erzeugen, indem ich auch eine virtuelle Methode innerhalb des Basisklassenkonstruktors aufrufe.
Nur weil man kann etwas Schlechtes tun nicht sein ein bedeuten Fehler , wenn Sie etwas von ihm zu bekommen.
quelle
InvalidProgramException
.Ich könnte mich irren, aber ich bin mir ziemlich sicher, dass
null
es niemals ein Szenario geben wird, in dem diesthis
zutrifft.Wie würden Sie zum Beispiel anrufen
CheckNull
?quelle
this
sich gegenseitig die Möglichkeit ausschließt, null zu sein - eine Art "Cogito, ergo sum" der Computerprogrammierung. Daher erscheintthis == null
mir Ihr Wunsch, den Ausdruck zu verwenden und ihn jemals wahr werden zu lassen, falsch.Ich bin mir nicht sicher, ob Sie danach suchen
Beispiel: UserID = CheckForNull (Request.QueryString ["UserID"], 147);
quelle