Suprimir advertencias de "nunca se usa" y "nunca se asigna a" en C #


107

Tengo un archivo HTTPSystemDefinitions.cs en el proyecto C # que básicamente describe el ISAPI de Windows más antiguo para el consumo mediante código administrado.

Esto incluye el conjunto completo de estructuras relevantes para la ISAPI, no todas o que son consumidas por código. En la compilación, todos los miembros de campo de estas estructuras están provocando una advertencia como la siguiente:

El campo de advertencia 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader' nunca se asigna y siempre tendrá su valor predeterminado nulo

o

Advertencia El campo 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus' nunca se usa

¿Se pueden desactivar con #pragma warning disable? Si es así, ¿cuáles serían los números de error correspondientes? Si no, ¿hay algo más que pueda hacer? Tenga en cuenta que solo sé qué hacer con este archivo, es importante que vea advertencias como estas provenientes de otros archivos.

Editar

Estructura de ejemplo: -

struct HTTP_FILTER_PREPROC_HEADERS
{
    //
    //  For SF_NOTIFY_PREPROC_HEADERS, retrieves the specified header value.
    //  Header names should include the trailing ':'.  The special values
    //  'method', 'url' and 'version' can be used to retrieve the individual
    //  portions of the request line
    //

    internal GetHeaderDelegate GetHeader;
    internal SetHeaderDelegate SetHeader;
    internal AddHeaderDelegate AddHeader;

    UInt32  HttpStatus;               // New in 4.0, status for SEND_RESPONSE
    UInt32  dwReserved;               // New in 4.0
}

¿Puede mostrar la declaración de esos campos, o más bien, la estructura en la que se encuentran? es decir. dar un ejemplo.
Lasse V. Karlsen

11
Si se trata de definiciones de interoperabilidad, normalmente las pondría [StructLayout(LayoutKind.Sequential)]para asegurarse de que el diseño de la memoria sea correcto (en la implementación actual será incluso sin este atributo, pero AFAIK no está garantizado). Si no recuerdo mal, el compilador de C # detecta la presencia de este atributo y suprime automáticamente esas advertencias, ya que sabe que los campos deben estar allí para la interoperabilidad. (Podría estar equivocado sobre esto, por lo tanto, publicar como un comentario en lugar de una respuesta).
Greg Beech

@Greg: Esa es información útil que investigaré. Preferiría no generar la advertencia en lugar de suprimirla.
AnthonyWJones

1
+1 para usar StructLayout. Parece más limpio que suprimir las propias advertencias.
Deanna

@GregBeech ¡Tienes razón! Eso todavía se aplica a los proyectos .NET Standard en VS2017.
zwcloud

Respuestas:


195

Sí, estos se pueden suprimir.

Normalmente, me opongo a suprimir las advertencias, pero en este caso, las estructuras utilizadas para la interoperabilidad requieren absolutamente que algunos campos estén presentes, aunque nunca tenga la intención (o pueda) usarlos, por lo que en este caso creo que debería estar justificado .

Normalmente, para suprimir esas dos advertencias, debería corregir el código ofensivo. El primero ("... nunca se usa") suele ser un olor a código de restos de versiones anteriores del código. Quizás se eliminó el código, pero los campos se dejaron atrás.

El segundo suele ser un olor a código para campos usados ​​incorrectamente. Por ejemplo, podría escribir incorrectamente el nuevo valor de una propiedad en la propiedad misma, sin escribir nunca en el campo de respaldo.


Para suprimir las advertencias de "El campo XYZ nunca se utiliza ", haga lo siguiente:

#pragma warning disable 0169
... field declaration
#pragma warning restore 0169

Para suprimir las advertencias para "El campo XYZ nunca está asignado y siempre tendrá su valor predeterminado XX ", haga lo siguiente:

#pragma warning disable 0649
... field declaration
#pragma warning restore 0649

Para encontrar esos números de advertencia usted mismo (es decir, ¿cómo supe usar 0169 y 0649), haga esto:

  • Compile el código como de costumbre, esto agregará algunas advertencias a su lista de errores en Visual Studio
  • Cambie a la ventana de salida y a la salida de compilación, y busque las mismas advertencias
  • Copie el código de advertencia de 4 dígitos del mensaje correspondiente, que debería verse así:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): advertencia CS 0649 : El campo 'ConsoleApplication19.Program.dwReserved' nunca se asigna y siempre tendrá su valor predeterminado 0


Advertencia : según el comentario de @Jon Hanna , tal vez algunas advertencias sean necesarias para esto, para los futuros buscadores de esta pregunta y respuesta.

  • Primero y más importante, el acto de suprimir una advertencia es similar a tragar pastillas para el dolor de cabeza. Claro, a veces puede ser lo correcto, pero no es una solución general. A veces, un dolor de cabeza es un síntoma real que no debes enmascarar, al igual que las advertencias. Siempre es mejor tratar de tratar las advertencias arreglando su causa, en lugar de simplemente eliminarlas ciegamente de la salida de la compilación.
  • Dicho esto, si necesita suprimir una advertencia, siga el patrón que expuse anteriormente. La primera línea de código #pragma warning disable XYZK, desactiva la advertencia para el resto de ese archivo , o al menos hasta que #pragma warning restore XYZKse encuentre el correspondiente . Minimice la cantidad de líneas en las que deshabilita estas advertencias. El patrón anterior deshabilita la advertencia para una sola línea.
  • Además, como menciona Jon, es una buena idea un comentario sobre por qué estás haciendo esto. Deshabilitar una advertencia es definitivamente un olor a código cuando se hace sin una causa, y un comentario evitará que los futuros mantenedores pasen tiempo preguntándose por qué lo hizo, o incluso eliminándolo y tratando de corregir las advertencias.

9
Recomendaría además de la respuesta anterior, que el alcance de la desactivación sea lo más pequeño posible (para evitar desactivarlo en algún lugar donde sea útil) y que siempre acompañe una desactivación con un comentario sobre por qué la desactiva, por ejemplo, //exists for interopen este caso.
Jon Hanna

Muchas gracias. Es una elección extraña que VS no incluya una columna para estos números en la ventana Lista de errores.
AnthonyWJones

2
Como dice Jon, comentar el "por qué" es muy importante. Además, normalmente agrego al menos parte del texto del mensaje de advertencia al comentario, por ejemplo, // Suprimir "nunca se asigna a ..." advertencia. Ahorre a los futuros mantenedores la molestia de tener que buscar el código de advertencia; después de todo, ¡podría ser usted!
Tom Bushell

1
No es inmediatamente obvio, pero puede usar Buscar en la ventana de salida a través de CTRL + F, escribir "advertencia", hacer clic en "Buscar todo" y obtener todas las advertencias rápidamente, con los números de advertencia mostrados. Dicho esto, el [StructLayout(LayoutKind.Sequential)]atributo maneja la interoperabilidad mucho mejor según el comentario de Greg Beech sobre la pregunta.
Ryan Buddicom

2
Comentando para decir que para los usuarios de Unity3D, los números de advertencia son 0414 para campos privados y 0219 para variables locales, no 169 (lo que arroja una advertencia sobre la imposibilidad de restaurar la advertencia).
Draco18s ya no confía en SE

14

Otra "solución" para corregir estas advertencias es crear la estructura public. Las advertencias no se emiten entonces porque el compilador no puede saber si los campos se están usando (asignados) fuera del ensamblado.

Dicho esto, los componentes de "interoperabilidad" normalmente no deberían ser públicos, sino internalo private.


2
Genial, esto oculta la advertencia ... pero configurar tal structcomo publices más probable que sea un error que la advertencia que estamos tratando de enmascarar. (Probablemente no debería exponer innecesariamente los tipos utilizados para la implementación interna y los tipos con campos públicos probablemente no pertenezcan a una API pública). Solo para reforzar su consejo de que esos tipos deberían ser "más bien internalo private" ;-).
binki,

Increíble gracias, esto es lo que necesitaba. Estoy usando JsonConvert.DeserializeObjecty estoy deserializando en una clase pública que solo tiene todas las propiedades expuestas para saber qué se devolverá. Convertirlo en una clase pública que esté vacía con todas las cadenas públicas es un código corto agradable y ahora no hay más advertencias. Tal vez sea mejor usar una clase dinámica ya que no tiene que indicar explícitamente qué hay en la matriz, pero creo que esta será una buena referencia para cualquiera que desee usar el objeto.
user1274820

6

Conseguí que VS generara el esqueleto de implementación System.ComponentModel.INotifyPropertyChangedy los eventos se implementaron como campos que desencadenaron las advertencias CS0067.

Como alternativa a la solución dada en la respuesta aceptada , convertí los campos en propiedades y la advertencia desapareció .

Esto tiene sentido ya que la sintaxis de declaraciones de propiedad sugar se compila en un campo más métodos getter y / o setter (agregar / eliminar en mi caso) que hacen referencia al campo. Esto satisface al compilador y las advertencias no se generan:

struct HTTP_FILTER_PREPROC_HEADERS
{
    //
    //  For SF_NOTIFY_PREPROC_HEADERS, retrieves the specified header value.
    //  Header names should include the trailing ':'.  The special values
    //  'method', 'url' and 'version' can be used to retrieve the individual
    //  portions of the request line
    //

    internal GetHeaderDelegate GetHeader {get;set;}
    internal SetHeaderDelegate SetHeader { get; set; }
    internal AddHeaderDelegate AddHeader { get; set; }

    UInt32 HttpStatus { get; set; }               // New in 4.0, status for SEND_RESPONSE
    UInt32 dwReserved { get; set; }               // New in 4.0
}

Su solución es mucho más elegante que deshabilitar la advertencia, pero puede interferir con algunos atributos de solo campo, por ejemplo, MarshalAsAttribute.
HuBeZa

1
Información: Los campos privados reales generados en esta situación pueden tener nombres "extraños" como <GetHeader>k__BackingField, según los detalles de implementación del compilador de C # utilizado.
Jeppe Stig Nielsen

1

Los usuarios de C / C ++ deben (void)var;suprimir las advertencias de variables no utilizadas. Acabo de descubrir que también puede suprimir las advertencias de variables no utilizadas en C # con operadores bit a bit:

        uint test1 = 12345;
        test1 |= 0; // test1 is still 12345

        bool test2 = true;
        test2 &= false; // test2 is now false

Ambas expresiones no producen advertencias de variables no utilizadas en los compiladores VS2010 C # 4.0 y Mono 2.10.


4
Funciona para uintotros tipos, pero no para Exception. ¿Conoces un truco genérico equivalente al C / C ++ var;?
manuell

1
@manuell ¡hola desde el futuro! Puede usar error.ToString();para una variable de tipoException
Sv443

Gracias a partir de ahora. Ese truco agrega código real en tiempo de ejecución, ¿verdad?
manuell
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.