c# - linguaggi - vs visual studio



(questo== null) in C#! (4)

A causa di un bug corretto in C # 4, il seguente programma stampa true . (Provalo su 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 in modalità Release, genera una InvalidProgramException. (In modalità Debug, funziona bene)

In VS2010 Beta 2, non viene compilato (non ho provato Beta 1); L'ho imparato nel modo più duro

C'è un altro modo per rendere this == null in puro C #?

https://src-bin.com


Answer #1

L'ho avuto! (e ha anche una prova)


Answer #2

La decompilazione non elaborata (Reflector senza ottimizzazioni) del binario in modalità Debug è:

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;
    }
}

Il metodo CompilerGenerated non ha senso; se si guarda l'IL (sotto), si chiama il metodo su una stringa nulla (!).

   .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 

In modalità Release, la variabile locale viene ottimizzata, quindi tenta di spingere una variabile inesistente sullo stack.

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

(Reflector si blocca quando lo si trasforma in C #)

EDIT : Qualcuno (Eric Lippert?) Sa perché il compilatore emette l' ldloc ?


Answer #3

Potrei sbagliarmi, ma sono abbastanza sicuro che se il tuo oggetto è null non ci sarà mai uno scenario dove this applica.

Ad esempio, come chiameresti CheckNull ?

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

Answer #4

Questa osservazione è stata pubblicata su in un'altra domanda oggi.

La grande risposta di Marc a questa domanda indica che secondo le specifiche (sezione 7.5.7), non dovresti essere in grado di accedere a this in quel contesto e la possibilità di farlo nel compilatore C # 3.0 è un bug. Il compilatore C # 4.0 si comporta correttamente in base alle specifiche (anche in Beta 1, questo è un errore di compilazione):

§ 7.5.7 Questo accesso

Un accesso di questo tipo consiste nella parola riservata.

questo accesso:

this

Un accesso di questo tipo è consentito solo nel blocco di un costruttore di istanze, un metodo di istanza o un accessorio di istanza.





compiler-bug