En C # 7 podemos usar
if (x is null) return;
en vez de
if (x == null) return;
¿Hay alguna ventaja en usar la nueva forma (ejemplo anterior) sobre la forma antigua?
¿La semántica es diferente?
¿Es solo cuestión de gustos? Si no, ¿cuándo debo usar uno sobre el otro?
Referencia: Novedades en C # 7.0 .
Respuestas:
Actualización: el compilador de Roslyn se ha actualizado para que el comportamiento de los dos operadores sea el mismo cuando no hay un operador de igualdad sobrecargado . Consulte el código en los resultados del compilador actual (
M1
yM2
en el código) que muestra lo que sucede cuando no hay un comparador de igualdad sobrecargado. Ambos tienen ahora el==
comportamiento de mejor desempeño . Si hay un comparador de igualdad sobrecargado, el código aún difiere .Consulte las versiones anteriores del compilador de Roslyn en el análisis a continuación.
Porque
null
no hay una diferencia con lo que estamos acostumbrados con C # 6. Sin embargo, las cosas se vuelven interesantes cuando cambiasnull
a otra constante.Toma esto por ejemplo:
La prueba rinde
a
. Si compara eso cono == (object)1
lo que hubiera escrito normalmente, hace una gran diferencia.is
toma en consideración el tipo al otro lado de la comparación. ¡Esta genial!Creo que el patrón
== null
vs. vs.is null
constante es algo que es muy familiar 'por accidente', donde la sintaxis delis
operador y el operador igual producen el mismo resultado.Como svick comentó,
is null
llamadasSystem.Object::Equals(object, object)
donde==
las llamadasceq
.IL para
is
:IL para
==
:Como estamos hablando
null
, no hay diferencia ya que esto solo hace una diferencia en las instancias . Esto podría cambiar cuando haya sobrecargado el operador de igualdad.fuente
is
llamadasobject.Equals(x, null)
, mientras se==
compila comoceq
. Pero el resultado debería ser el mismo, como dijiste.==
es un operador sobrecargable. Puede tener cualquier comportamiento que desee con él. Por ejemplo, esto implementado de manera extraña==
no le dirá si su instancia es realmente nula.is null
por otro lado, siempre devolverá verdadero para referencias nulas verdaderas :) Además, si tieneReferenceEquals
en su código, las bombillas VS 2017 sugerirán cambiar ais null
, no== null
(correctamente).is
ya no tiene la sobrecarga de una llamada a la función cuando se utiliza para verificar nula. Para prueba, vea el enlace publicado por @svick en los comentarios.Operador igual sobrecargado
De hecho, existe una diferencia en la semántica entre las dos comparaciones cuando se compara
null
con un tipo que ha sobrecargado al==
operador.foo is null
utilizará la comparación de referencia directa para determinar el resultado, mientras quefoo == null
, por supuesto, ejecutará el==
operador sobrecargado si existe.En este ejemplo, he introducido un "error" en el
==
operador sobrecargado , haciendo que siempre arroje una excepción si el segundo argumento esnull
:El código IL para
foo is null
utiliza laceq
instrucción para realizar una comparación de referencia directa:El código IL para
foo == null
utiliza una llamada al operador sobrecargado:Entonces, la diferencia es que si lo usa
==
, corre el riesgo de ejecutar código de usuario (que potencialmente puede tener problemas inesperados de comportamiento o rendimiento).Restricción de genéricos.
El uso de la
is null
construcción restringe el tipo a un tipo de referencia. El compilador asegura esto, lo que significa que no puede usaris null
un tipo de valor. Si tiene un método genérico, no podrá usarlo ais null
menos que el tipo genérico esté limitado a ser un tipo de referencia.Gracias a David Augusto Villa por señalar esto.
fuente