Devido a um erro corrigido no C # 4, o programa a seguir é impresso true
. (Experimente no 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()) { }
}
No VS2008 no modo Release, lança uma InvalidProgramException. (No modo de depuração, funciona bem)
No VS2010 Beta 2, ele não é compilado (não tentei o Beta 1); Eu aprendi isso da pior maneira
Existe alguma outra maneira de criar this == null
em c # puro?
Respostas:
Esta observação foi publicada no StackOverflow em outra pergunta hoje cedo.
A grande resposta de Marc para essa pergunta indica que, de acordo com a especificação (seção 7.5.7), você não deve poder acessar
this
nesse contexto e a capacidade de fazê-lo no compilador C # 3.0 é um bug. O compilador C # 4.0 está se comportando corretamente de acordo com as especificações (mesmo na Beta 1, esse é um erro de tempo de compilação):fonte
: base(CheckNull())
se o CheckNull não for estático e, da mesma forma, não poderá incorporar uma lambda vinculada à instância.this
noCheckNull
método é legal. O que não é legal é o implícita este acesso em() => CheckNull()
, essencialmente() => this.CheckNull()
, que está sendo executado fora do bloco de um construtor de instância. Concordo que a parte das especificações que cito se concentra principalmente na legalidade sintática dathis
palavra-chave, e provavelmente outra parte aborda esse problema com mais precisão, mas também é fácil extrapolar conceitualmente essa parte das especificações.A descompilação bruta (Refletor sem otimizações) do binário do modo Debug é:
O método CompilerGenerated não faz sentido; se você olhar para o IL (abaixo), ele está chamando o método em uma sequência nula (!).
No modo Release, a variável local é otimizada, portanto, tenta empurrar uma variável inexistente para a pilha.
(O refletor trava ao transformá-lo em c #)
Edição : Alguém (Eric Lippert?) Sabe por que o compilador emite o
ldloc
?fonte
Eu tive isso! (e tenho provas também)
fonte
Este não é um "bug". É você que está abusando do sistema de tipos. Você nunca deve passar uma referência à instância atual (
this
) para alguém dentro de um construtor.Eu poderia criar um "bug" semelhante chamando um método virtual também no construtor da classe base.
Só porque você pode fazer algo ruim não significa que é um bug quando você fica com ele.
fonte
InvalidProgramException
.Eu posso estar errado, mas tenho certeza de que, se seu objeto for
null
, nunca haverá um cenário ondethis
se aplique.Por exemplo, como você ligaria
CheckNull
?fonte
this
é mutuamente exclusiva da possibilidade de ser nula - uma espécie de "cogito, ergo sum" de programação de computadores. Portanto, seu desejo de usar a expressãothis == null
e de sempre tê-la retornado verdadeiro me parece equivocado.Não tenho certeza se é isso que você está procurando
exemplo: UserID = CheckForNull (Request.QueryString ["UserID"], 147);
fonte