La guía paso a paso o código que verás en este post es la solución más sencilla y efectiva que encontramos a tus dudas o dilema.
Solución:
Es debido a la diferencia del compilador.
En este violín, https://dotnetfiddle.net/5GgGNS, puede ver el error, que se omite en el compilador mono.
Creo que el error es válido debido al hecho de que esta línea
if (myDict?.TryGetValue("hello", out var value) == true)
no se garantiza que inicialice la variable local value
.
Si lo reescribieras a:
if (myDict?.TryGetValue("hello", out var value) == null)
intentaría acceder value
.
Ahora el null
valor, o true
en su caso, podría ser el valor de retorno de una función, que solo se conocería en tiempo de ejecución.
Pero, dado que todas las variables básicamente siempre se inicializan, es solo una característica del compilador.
Por otro lado, según las especificaciones de C#5:
Una variable local introducida por una declaración de variable local no se inicializa automáticamente y, por lo tanto, no tiene un valor predeterminado. A los efectos de la comprobación de la asignación definitiva, una variable local introducida por una declaración de variable local se considera inicialmente no asignada. Una declaración de variable local puede incluir un inicializador de variable local, en cuyo caso la variable se considera definitivamente asignada solo después de la expresión de inicialización (§5.3.3.4).
Pero su código es C# 6.
Entonces mi conclusión es que los compiladores lo interpretan de manera diferente. El compilador de Microsoft toma la ?.
operador en cuenta. Debería archivarlo como un error, o al menos encontrarlo, tal vez incluso en ambas partes.
Argumentación
Dato curioso, si usas este código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
static void Main()
//Your code goes here
Dictionary myDict = null;
if (myDict?.TryGetValue("hello", out var value) == null)
Console.WriteLine("Hello" + value.ToString());
[using https://www.jdoodle.com/compile-c-sharp-online , mono 5.10.1]
Verá la inicialización real para default(T)
en el trabajo. la salida es Hello0
. Sin embargo, es notable porque debido a la ?
y el hecho de que myDict
es null
, TryGetValue
no debería ser llamado e irse value
“no inicializado”.
Él null-Los operadores condicionales están en cortocircuito. Es decir, si una operación en una cadena de operaciones de acceso a elementos o miembros condicionales devuelve nullel resto de la cadena no se ejecuta.
fuente
Pero…, ya que no hay variables sin inicializar; si compila, el compilador se asegurará de que su comportamiento no sea indefinido.
Entonces, desde value
es inicializado, en tiempo de ejecución, la pregunta sigue siendo si es un error de compilador válido en el momento de la compilación. Con respecto a la intención de tiempo de ejecución del código (y es por eso que el error estaba allí en primer lugar), pero creo que sigue siendo un área gris.
Tenga en cuenta que de acuerdo con este default(T)
no se puede anular, lo que en realidad no conduciría a ninguna condición en la que falle.
Al ejecutar esta pequeña prueba:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
static void Main()
//Your code goes here
Dictionary myDict = null;
if (myDict?.Bar(out var test) == null)
Console.WriteLine("does hit");
static class Foo
public static object Bar(this Dictionary input, out int test)
test = 3;
Console.WriteLine("does not hit");
return 1;
[using https://www.jdoodle.com/compile-c-sharp-online , mono 5.10.1]
La salida se convierte en:
does hit
Y puede verificar el comportamiento correcto en tiempo de ejecución del ?.
operador.
Él null condicional ?.
elimina la garantía de que value
será asignado a desde TryGetValue
sólo se llamará condicionalmente si myDict
no es null
.
Usted hace cumplir la asignación de value
dentro de if
declaración posterior con == true
ya que el lado izquierdo regresara null
Si TryGetValue
no se llama por myDict
siendo en sí mismo null. El compilador, sin embargo, no puede dar este salto de inferencia en el caso general, por lo que debe ayudarlo probando myDict
por null
de antemano (y saltándose ?.
) o inicializando value
antemano.
Acuérdate de que tienes la opción de decir .