Saltar al contenido

¿Por qué el compilador arroja el error CS0165: uso de una variable local no asignada?

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 valuees 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 .

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *