variable validar safety operator operador diferente c# null switch-statement var c#-7.0

c# - validar - cambiar con var/nulo comportamiento extraño



operador null c# (3)

Dentro de una instrucción de switch coincidencia de patrón que usa un case para un tipo explícito se pregunta si el valor en cuestión es de ese tipo específico o de un tipo derivado. Es el equivalente exacto de is

switch (someString) { case string s: } if (someString is string)

El valor null no tiene un tipo y, por lo tanto, no cumple ninguna de las condiciones anteriores. El tipo estático de someString no entra en juego en ninguno de los ejemplos.

Sin embargo, el tipo var en la coincidencia de patrones actúa como comodín y coincidirá con cualquier valor, incluido null .

El caso default aquí es código muerto. El case var o coincidirá con cualquier valor, nulo o no nulo. Un caso no predeterminado siempre prevalece sobre uno default , default tanto, el default nunca será afectado. Si miras el IL, verás que ni siquiera se emite.

De un vistazo, puede parecer extraño que esto se compile sin ninguna advertencia (definitivamente me desanimó). Pero esto coincide con el comportamiento de C # que se remonta a 1.0. El compilador permite casos default incluso cuando puede probar trivialmente que nunca será afectado. Considere como ejemplo lo siguiente:

bool b = ...; switch (b) { case true: ... case false: ... default: ... }

Aquí el default nunca se verá afectado (incluso para bool que tiene un valor que no es 1 o 0). Sin embargo, C # ha permitido esto desde 1.0 sin previo aviso. La coincidencia de patrones simplemente coincide con este comportamiento aquí.

Dado el siguiente código:

string someString = null; switch (someString) { case string s: Console.WriteLine("string s"); break; case var o: Console.WriteLine("var o"); break; default: Console.WriteLine("default"); break; }

¿Por qué coincide la sentencia switch en el case var o ?

Tengo entendido que la case string s no coincide cuando s == null porque (efectivamente) (null as string) != null evalúa como falso. IntelliSense en VS Code me dice que o es una string . ¿Alguna idea?

Similar a: C # 7 caso de interruptor con cheques nulos


Es porque el case <Type> coincide con el tipo dinámico (tiempo de ejecución), no con el tipo estático (tiempo de compilación). null no tiene un tipo dinámico, por lo que no puede coincidir con una string . var es solo la alternativa.

(Publicando porque me gustan las respuestas cortas).


Estoy reuniendo varios comentarios de Twitter aquí; esto es realmente nuevo para mí, y espero que jaredpar salte con una respuesta más completa, pero; versión corta como la entiendo:

case string s:

se interpreta como if(someString is string) { s = (string)someString; ... if(someString is string) { s = (string)someString; ... o if((s = (someString as string)) != null) { ... } - cualquiera de los cuales implica una prueba null - que falló en su caso; a la inversa:

case var o:

donde el compilador resuelve o como string es simplemente o = (string)someString; ... o = (string)someString; ... - no hay prueba null , a pesar de que se ve similar en la superficie, solo con el compilador que proporciona el tipo.

finalmente:

default:

aquí no se puede alcanzar , porque el caso anterior atrapa todo. Esto puede ser un error del compilador porque no emitió una advertencia de código inalcanzable.

Estoy de acuerdo en que esto es muy sutil, matizado y confuso. Pero aparentemente el case var o escenario tiene usos con propagación nula ( o?.Length ?? 0 etc.). Estoy de acuerdo en que es extraño que esto funcione de manera muy diferente entre var o y string s , pero es lo que hace actualmente el compilador.