2010-04-29 19 views
18

Alguien de mi equipo intentó corregir una advertencia de 'variable no utilizada' en una cláusula de captura vacía.C# El compilador debería dar una advertencia pero no?

try { ... } catch (Exception ex) { } 

-> da una advertencia acerca de ex que no se está utilizando. Hasta aquí todo bien.

La solución fue algo como esto:

try { ... } catch (Exception ex) { string s = ex.Message; } 

Al ver esto, pensé "Simplemente genial, por lo que ahora el compilador se quejará de s no se está utilizando."

¡Pero no es así! No hay advertencias en ese fragmento de código y no puedo entender por qué. ¿Algunas ideas?

PS. Sé que las cláusulas catch-all que silencian las excepciones son algo malo, pero ese es un tema diferente. También sé que la advertencia inicial se elimina mejor al hacer algo como esto, ese tampoco es el punto.

try { ... } catch (Exception) { } 

o

try { ... } catch { } 
+0

Consejo: Utilice el 'catch (Exception)' en lugar. Si desea ver la excepción en el depurador, use '$ exception'. – Brian

Respuesta

25

En este caso, el compilador detecta que s está escrito, pero no leer, y suprime deliberadamente la advertencia

La razón se debe a que C# es un lenguaje de recolección de basura. , lo creas o no.

¿Cómo darse cuenta de eso?

Bueno, tenga en cuenta lo siguiente.

Tiene un programa que llama a un método DoIt() que devuelve una cadena. No tiene el código fuente para DoIt(), pero desea examinar en el depurador cuál es su valor de retorno.

Ahora en su caso particular está utilizando DoIt() por sus efectos secundarios, no por su valor de retorno. Así que decir

DoIt(); // discard the return value 

Ahora que va a depurar su programa y que vaya a mirar el valor de retorno de DoIt() y no está ahí porque por el momento se rompe el depurador después de la llamada a DoIt(), el recolector de basura ya pudo haber limpiado la cadena no utilizada.

Y, de hecho, el depurador gestionado no tiene ninguna función para "ver lo devuelto por la llamada al método anterior". El depurador de C++ no administrado tiene esa característica porque puede mirar el registro EAX donde el valor de retorno descartado todavía está activo, pero no tiene garantía en el código administrado de que el valor devuelto esté vivo si fue descartado.

Ahora, uno podría argumentar que esta es una característica útil y que el equipo del depurador debería agregar una característica por la cual los valores devueltos se mantienen vivos si hay un punto de interrupción del depurador inmediatamente después de la ejecución de un método. Esa sería una buena característica, pero soy la persona equivocada para pedirla; ve a preguntar al equipo de depuración.

¿Qué debe hacer el desarrollador de pobres C#? Cree una variable local, almacene el resultado en la variable local y luego examine el local en el depurador. El depurador does asegura que los locales no sean recolectados de manera agresiva.

Así que hazlo y luego el compilador te advierte que tienes un local que solo está escrito y nunca lee porque lo que hace la lectura no es parte del programa, es el desarrollador sentado allí viendo el depurador. ¡Esa es una experiencia de usuario muy irritante! Por lo tanto, detectamos la situación en la que un valor no constante se está asignando a una variable local o campo que nunca es lea, y suprima esa advertencia. Si cambia su código para que en su lugar diga string s = "hello";, comenzará a recibir la advertencia porque el compilador razona, bueno, esto no puede ser alguien que esté trabajando alrededor de las limitaciones del depurador porque el valor es allí donde el desarrollador ya puede leerlo sin el depurador.

Eso lo explica. Existen numerosos otros casos en los que suprimimos advertencias sobre variables que nunca se leen; un detailed exegisis of all the compiler's policies para cuando reportemos advertencias y cuando no nos tome bastante tiempo para escribir, así que creo que lo dejaré así.

1

Creo que la persona que responde a esto tendrá una idea de cómo funciona el compilador. Sin embargo, algo como FxCop probablemente captaría esto.

9

La variable s se usa ... para mantener una referencia a ex.Message. Si tuvieras solo una cuerda s; obtendrías la advertencia.

+0

Supongo que tienes razón. "object a = String.Empty;" tampoco muestra una advertencia de compilación. Parece dar solo la advertencia sobre los tipos de valor (no anulables) –

+0

Pero si solo asigna una variable y nunca la usa, el compilador dice 'La variable 'x' está asignada pero su valor nunca se usa' –

+0

Esto solo ocurre para ciertos tipos, creo que los tipos de valor específicamente. Tales como 'bool'. Pero los tipos de referencias, como 'string', tradicionalmente no se quejan. –

1

Las propiedades son solo métodos, y no hay nada que impida que alguien ponga algún código que haga algo en la propiedad ex.Message. Por lo tanto, aunque no esté haciendo nada con s, llamar a ex.Message PODRÍA tener valor ....

0

El análisis estático es algo limitado en lo que puede lograr hoy. (Aunque como señaló Eric no porque no sabe en este caso)

Los nuevos Contratos de Código en .NET 4 mejoran considerablemente la comprobación estática y un día estoy seguro de que obtendrá más ayuda con errores obvios Me gusta esto.

Si ha probado los contratos de código, sabrá sin embargo que hacer un análisis estático exhaustivo de su código no es fácil, puede demorar minutos después de cada compilación. ¿Alguna vez el análisis estático podrá encontrar todos los problemas como este en tiempo de compilación? Probablemente no: vea http://en.wikipedia.org/wiki/Halting_problem.

+1

Este problema en particular no tiene nada que ver con el problema de detención. El compilador detecta la condición de advertencia y suprime deliberadamente el informe. –

+0

OK, gracias. Supuse que era un límite sobre qué tan lejos estaba sucediendo el análisis estático en el compilador actual, no que lo estaba haciendo y luego lo descarté. La detención del enlace de estado fue solo para ilustrar la dificultad del análisis estático. –

1

No es realmente el trabajo de un compilador resolver cada instancia y caso de esquina cuando una variable puede o no ser utilizada. Algunos son fáciles de detectar, algunos son más problemáticos. Errar por el lado de la precaución es lo sensato que hay que hacer (especialmente cuando las advertencias se pueden configurar para ser tratadas como errores; imagínese si el software no se compiló solo porque el compilador pensó que no estaba usando algo que era). equipo de Microsoft compilador dice específicamente:

" ... nuestra guía para los clientes que están interesados ​​en descubrir no utilizados elementos en su código es utilizar FxCop Se puede descubrir los campos no utilizados y datos más interesantes sobre. tu código."

- Ed Maurer, Development Lead, Managed Compiler Platform

1

ReSharper atraparía que

Cuestiones relacionadas