Pergunta

Devido a um bug que foi corrigido em C # 4, o seguinte programa imprime true. (Experimente-o em 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()) { }
}

Em VS2008 no modo de versão, ele lança uma InvalidProgramException. (No modo de depuração, ele funciona bem)

Em VS2010 Beta 2, que não compila (eu não tentar Beta 1); Eu aprendi isso da pior maneira

Existe alguma outra maneira de fazer this == null em puro C #?

Foi útil?

Solução

Esta observação foi publicado em StackOverflow em outra pergunta hoje cedo.

Marc 's grande resposta para essa pergunta indica que, de acordo com a especificação (seção 7.5.7), você não deve ser capaz de acesso this nesse contexto e a capacidade de fazê-lo em C # 3.0 do compilador é um bug. C # 4.0 do compilador está se comportando corretamente de acordo com as especificações (mesmo no Beta 1, este é um erro de tempo de compilação):

§ 7.5.7 Este acesso

A este acesso consiste na this palavra reservada.

este acesso:

this

A este acesso é permitido apenas no bloco de um construtor de instância, um método de instância, ou um acessor exemplo.

Outras dicas

A descompilação raw (Refletor sem otimizações) do binário modo de depuração é:

private class Derived : Program.Base
{
    // Methods
    public Derived()
    {
        base..ctor(new Func<string>(Program.Derived.<.ctor>b__0));
        return;
    }

    [CompilerGenerated]
    private static string <.ctor>b__0()
    {
        string CS$1$0000;
        CS$1$0000 = CS$1$0000.CheckNull();
    Label_0009:
        return CS$1$0000;
    }

    private string CheckNull()
    {
        string CS$1$0000;
        CS$1$0000 = "Am I null? " + ((bool) (this == null));
    Label_0017:
        return CS$1$0000;
    }
}
método

O CompilerGenerated não faz sentido; se você olhar para a IL (abaixo), que está chamando o método em um nulo string (!).

   .locals init (
        [0] string CS$1$0000)
    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: stloc.0 
    L_0007: br.s L_0009
    L_0009: ldloc.0 
    L_000a: ret 

No modo Release, a variável local é otimizado distância, por isso tenta empurrar uma variável inexistente para a pilha.

    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: ret 

(Reflector falha quando transformando-o em C #)


Editar :? Alguém (? Eric Lippert) sabe por que o compilador emite o ldloc

Eu tive isso! (E prova obtida também)

text alt

Este não é um "bug". Isto é você abusar do sistema tipo. Que nunca se deve passar uma referência para a instância atual (this) para qualquer um dentro de um construtor.

Eu poderia criar um "bug" semelhante ao chamar um método virtual dentro do construtor da classe base também.

Só porque você pode fazer algo ruim não significa que é um bug quando você começa pouco por ela.

Eu posso estar errado, mas eu tenho certeza que se o seu objeto é null há nunca vai ser um cenário onde this aplica.

Por exemplo, como você chamaria CheckNull?

Derived derived = null;
Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException

Não sei se isso é o que você está procurando

    public static T CheckForNull<T>(object primary, T Default)
    {
        try
        {
            if (primary != null && !(primary is DBNull))
                return (T)Convert.ChangeType(primary, typeof(T));
            else if (Default.GetType() == typeof(T))
                return Default;
        }
        catch (Exception e)
        {
            throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString());
        }
        return default(T);
    }

exemplo: IDUtilizador = CheckForNull (Request.QueryString [ "ID de utilizador"], 147);

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top