¿Cuál es la diferencia entre" x es null "y"x == null"?


En C# 7 podemos usar

if (x is null) return;

En lugar de

if (x == null) return;

¿Hay alguna ventaja de usar la nueva forma (ejemplo anterior) que la sintaxis antigua?

La semántica es diferente?

Es solo una cuestión de gusto? Si no, cuándo usar uno u otro.

Referencia.

Author: Maniero, 2016-11-18

2 answers

Update: El compilador de Roslyn se ha actualizado para hacer que el comportamiento de los dos operadores sea el mismo cuando no hay un operador de igualdad sobrecargado. Por favor vea el código en los resultados del compilador actual (M1 y M2 en el código) que muestra lo que sucede cuando no hay comparador de igualdad sobrecargado. Ambos ahora tienen el mejor comportamiento ==. Si hay un comparador de igualdad sobrecargado, el código todavía difiere.

Véase para versiones anteriores del compilador de Roslyn el siguiente análisis.


Para null no hay una diferencia con lo que estamos acostumbrados con C# 6. Sin embargo, las cosas se vuelven interesantes cuando cambias null a otra constante.

Tome esto por ejemplo:

Test(1);

public void Test(object o)
{
    if (o is 1) Console.WriteLine("a");
    else Console.WriteLine("b");
}

La prueba produce a. Si comparas eso con o == (object)1 lo que habrías escrito normalmente, hace una gran diferencia. is toma en consideración el tipo en el otro sitio de la comparación. Eso es ¡Órale!

Creo que el patrón constante == null vs. is null es solo algo que es muy familiar 'por accidente', donde la sintaxis del operador is y el operador igual producen el mismo resultado.


Como svick, comentó, is null llamadas System.Object::Equals(object, object) donde == llamadas ceq.

IL para is:

IL_0000: ldarg.1              // Load argument 1 onto the stack
IL_0001: ldnull               // Push a null reference on the stack
IL_0002: call bool [mscorlib]System.Object::Equals(object, object) // Call method indicated on the stack with arguments
IL_0007: ret                  // Return from method, possibly with a value

IL para ==:

IL_0000: ldarg.1              // Load argument 1 onto the stack
IL_0001: ldnull               // Push a null reference on the stack
IL_0002: ceq                  // Push 1 (of type int32) if value1 equals value2, else push 0
IL_0004: ret                  // Return from method, possibly with a value

Ya que estamos hablando de null, no hay diferencia desde este solo hace una diferencia en las instancias. Esto podría cambiar cuando se ha sobrecargado el operador de igualdad.

 109
Author: Patrick Hofman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-15 08:28:06

De hecho, hay una diferencia en la semántica entre las dos comparaciones. El caso de borde se presenta cuando se compara null con un tipo que ha sobrecargado el operador ==.

foo is null utilizará la comparación de referencia directa para determinar el resultado, mientras que foo == null por supuesto ejecutará el operador == sobrecargado si existe.

En este ejemplo he introducido un error en el operador overloaded ==, haciendo que siempre devuelva false si el segundo argumento es null:

void Main()
{
    Foo foo = null;

    if (foo is null) Console.WriteLine("foo is null"); // This condition is met
    if (foo == null) Console.WriteLine("foo == null"); // This condition is NOT met
}

public class Foo
{
    public static bool operator ==(Foo foo1, Foo foo2)
    {
        if (object.Equals(foo2, null)) return false;
        return object.Equals(foo1, foo2);
    }

    // ...
}

El código IL para foo is null utiliza la instrucción ceq para realizar una comparación de referencia directa:

IL_0003:  ldloc.0     // foo
IL_0004:  ldnull      
IL_0005:  ceq

El código IL para foo == null utiliza una llamada al operador sobrecargado:

IL_0016:  ldloc.0     // foo
IL_0017:  ldnull      
IL_0018:  call        UserQuery+Foo.op_Equality

Así que la diferencia es que si usas == corres el riesgo de ejecutar código de usuario (que puede ser defectuoso o tener un mal rendimiento).

 23
Author: Thorkil Holm-Jacobsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-12 07:37:02