Pregunta

Debido a un error que se corrigió en C # 4, el siguiente programa imprime true . (Pruébelo en 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()) { }
}

En VS2008 en modo Release, arroja una InvalidProgramException. (En modo de depuración, funciona bien)

En VS2010 Beta 2, no se compila (no probé Beta 1); Aprendí que por las malas

¿Hay alguna otra manera de hacer que this == null en C # puro?

¿Fue útil?

Solución

Esta observación se ha publicado en StackOverflow en otro pregunta más temprano hoy.

Marc 's gran respuesta a esa pregunta indica que de acuerdo con las especificaciones (sección 7.5.7), no debe poder acceder a this en ese contexto y la capacidad de hacerlo en el compilador C # 3.0 es un error. El compilador C # 4.0 se comporta correctamente de acuerdo con las especificaciones (incluso en Beta 1, este es un error de tiempo de compilación):

  

& # 167; 7.5.7 Este acceso

     

Un este acceso consiste en la palabra reservada this .

     

este-acceso:

this
     

Un this-access solo está permitido en el bloque de un constructor de instancias, un método de instancia o un descriptor de acceso de instancia.

Otros consejos

La descompilación sin procesar (Reflector sin optimizaciones) del binario en modo de depuración es:

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

El método CompilerGenerated no tiene sentido; si observa el IL (a continuación), está llamando al método en una cadena (!) nula.

<*>

En el modo Release, la variable local se optimiza, por lo que intenta insertar una variable no existente en la pila.

<*>

(El reflector se bloquea al convertirlo en C #)


EDITAR : ¿Alguien (Eric Lippert?) sabe por qué el compilador emite el ldloc ?

¡He tenido eso! (y obtuve pruebas también)

texto alternativo ??

Esto no es un "error". Estás abusando del sistema de tipos. Se supone que nunca debe pasar una referencia a la instancia actual ( this ) a nadie dentro de un constructor.

Podría crear un "error" similar llamando también a un método virtual dentro del constructor de la clase base.

El hecho de que pueda hacer algo malo no significa que sea un error cuando lo muerde.

Podría estar equivocado, pero estoy bastante seguro de que si su objeto es nulo , nunca habrá un escenario en el que se aplique this .

Por ejemplo, ¿cómo llamaría a CheckNull ?

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

No estoy seguro si esto es lo que estás buscando

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

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top