Recientemente descubrí que el siguiente código compila y funciona como se esperaba en VS2017. Pero no puedo encontrar ningún tema/documentación sobre esto. Así que tengo curiosidad si es legítimo usar esta sintaxis:
class Program { static void Main(string[] args) { var o = new object(); Console.WriteLine(o is null); o = null; Console.WriteLine(o is null); Console.ReadLine(); } }Por cierto, esto no funciona en VS2015
Sí, es válido escribir o is null , pero esto no es equivalente a o == null . El código
static bool TestEquality(object value) => value == null;se compila siguiendo las instrucciones IL.
IL_0000: ldarg.0 IL_0001: ldnull IL_0002: ceq IL_0004: retEl caso de coincidencia de patrones compilado de la siguiente manera:
static bool TestPatternMatching(object value) => value is null; IL_0000: ldnull IL_0001: ldarg.0 IL_0002: call bool [System.Runtime]System.Object::Equals(object, object) IL_0007: retEntonces, la coincidencia de patrones o es nulo es equivalente a
Object.Equals(value, null);Entonces, en la mayoría de los casos, o es nulo y o == nulo se comportará de la misma manera. Excepto que la variante de igualdad es un poco más rápida. ¡PERO! Las cosas cambiarán dramáticamente si reemplazamos el objeto con la siguiente clase.
class TestObject { public static bool operator ==(TestObject lhs, TestObject rhs) => false; public static bool operator !=(TestObject lhs, TestObject rhs) => false; }y métodos con
static bool TestEquality(TestObject value) => value == null; static bool TestPatternMatching(TestObject value) => value is null;La coincidencia de patrones permanecerá igual, pero la variante de igualdad utilizará el siguiente IL
IL_0000: ldarg.0 IL_0001: ldnull IL_0002: call bool PatternMatchingTest.TestObject::op_Equality(class PatternMatchingTest.TestObject, class PatternMatchingTest.TestObject) IL_0007: retAquí podemos ver que el operador == está usando la sobrecarga de TestObject como se esperaba. Pero o es nulo y o==null dará resultados diferentes. Así que tenga cuidado al usar la coincidencia de patrones es el operador.
Sí, es totalmente válido. Esto utiliza la función de coincidencia de patrones de C# 7, que está disponible con expresiones is y declaraciones switch/case . (El hecho de que requiera C# 7 es la razón por la que no funciona en VS2015). Por ejemplo:
// Type check, with declaration of new variable if (o is int i) { Console.WriteLine(i * 10); } // Simple equality check if (o is 5) {} Es probable que las verificaciones de igualdad como la última, particularmente para null , no sean muy útiles para la is de patrones, pero son más útiles para cambiar/caso:
switch (o) { case int i when i > 100000: Console.WriteLine("Large integer"); break; case null: Console.WriteLine("Null value"); break; case string _: Console.WriteLine("It was a string"); break; default: Console.WriteLine("Not really sure"); break; }Para obtener más detalles sobre las características de C# 7, consulte la publicación de blog de MSDN de Mads Torgersen .