5

He notado algo peculiar sobre Visual Studio. En primer lugar, intente escribir esto (C#) en algún lugar de una función:Advertencia de referencia nula de Visual Studio: ¿por qué no hay ningún error?

class Foo 
{ 
    public void Bar() 
    { 
     string s; 
     int i = s.Length; 
    } 
} 

Ahora, de inmediato se marcará el s en s.Length como un error, diciendo "Use of unassigned local variable 's'". Por otro lado, probar este código:

class Foo 
{ 
    private string s; 
    public void Bar() 
    { 
     int i = s.Length; 
    } 
} 

Compilará, y subrayar la s en private string s con una advertencia, diciendo "Field 'Foo.s' is never assigned to, and will always have its default value null".

Ahora, si VS es tan inteligente y sabe que s siempre será nulo, ¿por qué no es un error obtener su longitud en el segundo ejemplo? Mi conjetura original fue, "solo da un error de compilación si el compilador simplemente no puede completar su trabajo. Dado que el código técnicamente se ejecuta siempre y cuando nunca se llame a Bar(), es solo una advertencia". Excepto que la explicación es invalidada por el primer ejemplo. Todavía podría ejecutar el código sin error siempre que nunca llame a Bar(). Entonces, ¿qué da? Solo un descuido, ¿o me estoy perdiendo algo?

Respuesta

8

El primer ejemplo (el error) es un ejemplo del seguimiento del compilador definite-assignment y solo se aplica a las variables locales. Debido al contexto limitado, el compilador tiene un control hermético de esta situación. Tenga en cuenta que s no es nulo, no está definido.

En el segundo ejemplo, s es un campo (y el valor predeterminado es nulo). No hay error de compilación, pero siempre se detectará en tiempo de ejecución. Este caso particular podría quedar atrapado, pero este tipo de error no es en general detectable por el compilador.
Por ejemplo, puede agregar un método Bar2() que asigna una cadena al s, pero llámelo más tarde que Bar(), o no lo escriba en absoluto. Eso eliminaría la advertencia, pero no el error de tiempo de ejecución.

Así es por diseño.

0

La única conjetura que puedo hacer es que en el segundo ejemplo, s puede cambiarse a través de la reflexión (usando BindingFlags.Private para acceder al miembro privado).

0

En primera muestra s es una variable local y el compilador puede comprobar que easialy s varible no fue asignado antes de que sea utilizado.

En la segunda, s es una variable global y es posible que se haya inicializado en otra parte de una clase.

+0

s ¿no es global, es una instancia -campo. –

3

Para el segundo ejemplo, el código es válido, puede que no se ejecute correctamente. Aquí hay varios casos en los que este programa podría ejecutar "con éxito"

  • El compilador no es 100% correcto. Es posible que "s" tenga un valor no nulo si una instancia se modifica mediante reflexión.
  • El programa se puede ejecutar sin error si la barra método no se llamó nunca
  • Este programa podría ser un programa de prueba que está desencadenando una NullReferenceException por razones de prueba
Cuestiones relacionadas