Domanda

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

In VS2010 Beta 2, non viene compilato (non ho provato Beta 1); L'ho imparato a mie spese

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

È stato utile?

Soluzione

Questa osservazione è stata pubblicata su StackOverflow in altro domanda prima di oggi.

Marc 's un'ottima risposta 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, si tratta di un errore di tempo di compilazione):

  

§ 7.5.7 Questo accesso

     

Un questo accesso è costituito dalla parola riservata this .

     

questo accesso:

this
     

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

Altri suggerimenti

La decompilazione grezza (Reflector senza ottimizzazioni) del binario della 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
   .locals init (
        [0] string CS$1
    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: ret 
) 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
; CS$1<*> = CS$1<*>.CheckNull(); Label_0009: return CS$1<*>; } private string CheckNull() { string CS$1<*>; CS$1<*> = "Am I null? " + ((bool) (this == null)); Label_0017: return CS$1<*>; } }

Il metodo CompilerGenerated non ha senso; se guardi IL (sotto), sta chiamando il metodo su una stringa (!) nulla.!

<*>

In modalità Rilascio, la variabile locale è ottimizzata, quindi cerca di inserire una variabile inesistente nello stack.

<*>

(Reflector si arresta in modo anomalo quando lo si trasforma in C #)


MODIFICA : qualcuno (Eric Lippert?) sa perché il compilatore emette il ldloc ?

L'ho avuto! (e anche le prove)

alt text

Questo non è un bug " bug " ;. Stai abusando del sistema dei tipi. Non devi mai passare un riferimento all'istanza corrente ( this ) a chiunque all'interno di un costruttore.

Potrei creare un simile "errore" chiamando un metodo virtuale anche nel costruttore della classe base.

Solo perché puoi fare qualcosa di male non significa che si tratta di un bug quando ne rimani morso.

Potrei sbagliarmi, ma sono abbastanza sicuro che il tuo oggetto sia null non ci sarà mai uno scenario in cui questo si applica.

Ad esempio, come chiameresti CheckNull ?

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

Non sono sicuro se questo è quello che stai cercando

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

esempio: UserID = CheckForNull (Request.QueryString [" UserID "], 147);

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top