En raison d'un bogue corrigé en C # 4, le programme suivant s'imprime true
. (Essayez-le dans 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()) { }
}
Dans VS2008 en mode Release, il lève une InvalidProgramException. (En mode débogage, cela fonctionne très bien)
Dans VS2010 Beta 2, il ne compile pas (je n'ai pas essayé la Beta 1); J'ai appris que la manière dure
Existe-t-il un autre moyen de créer this == null
en pur C #?
Réponses:
Cette observation a été publiée sur StackOverflow dans une autre question plus tôt dans la journée .
La bonne réponse de Marc à cette question indique que selon la spécification (section 7.5.7), vous ne devriez pas pouvoir accéder
this
dans ce contexte et la possibilité de le faire dans le compilateur C # 3.0 est un bogue. Le compilateur C # 4.0 se comporte correctement selon la spécification (même en bêta 1, il s'agit d'une erreur de compilation):la source
: base(CheckNull())
si CheckNull n'est pas statique, et de même, vous ne devriez pas être en mesure d'insérer un lambda lié à une instance.this
dans laCheckNull
méthode est légal. Ce qui n'est pas légal, c'est l' accès implicite this- in() => CheckNull()
, essentiellement() => this.CheckNull()
, qui s'exécute en dehors du bloc d'un constructeur d'instance. Je conviens que la partie de la spécification que je cite est principalement axée sur la légalité syntaxique duthis
mot-clé, et probablement une autre partie aborde cette question plus précisément, mais il est également facile d'extrapoler conceptuellement à partir de cette partie de la spécification.La décompilation brute (réflecteur sans optimisations) du binaire du mode Debug est:
La méthode CompilerGenerated n'a pas de sens; si vous regardez l'IL (ci-dessous), il appelle la méthode sur une chaîne nulle (!).
En mode Release, la variable locale est optimisée, donc elle essaie de pousser une variable inexistante sur la pile.
(Le réflecteur plante en le transformant en C #)
EDIT : Est-ce que quelqu'un (Eric Lippert?) Sait pourquoi le compilateur émet le
ldloc
?la source
J'ai eu ça! (et j'ai aussi une preuve)
la source
Ce n'est pas un "bug". C'est vous qui abusez du système de types. Vous n'êtes jamais censé passer une référence à l'instance actuelle (
this
) à quiconque dans un constructeur.Je pourrais créer un "bogue" similaire en appelant également une méthode virtuelle dans le constructeur de la classe de base.
Ce n'est pas parce que vous pouvez faire quelque chose de mal que c'est un bogue quand vous êtes mordu.
la source
InvalidProgramException
.Je peux me tromper, mais je suis presque sûr que si votre objectif est
null
qu'il n'y aura jamais de scénario où celathis
s'applique.Par exemple, comment appelleriez-vous
CheckNull
?la source
this
s'exclut mutuellement de la possibilité d'être nul - une sorte de "Cogito, ergo sum" de la programmation informatique. Par conséquent, votre désir d'utiliser l'expressionthis == null
et de la faire revenir vrai me semble erroné.Je ne sais pas si c'est ce que vous recherchez
exemple: UserID = CheckForNull (Request.QueryString ["UserID"], 147);
la source