Suppression des avertissements «n'est jamais utilisé» et «n'est jamais affecté à» en C #

107

J'ai un fichier HTTPSystemDefinitions.cs dans le projet C # qui décrit essentiellement les anciennes fenêtres ISAPI pour la consommation par code managé.

Cela inclut l'ensemble complet des structures pertinentes pour l'ISAPI pas toutes ou qui sont consommées par le code. Lors de la compilation, tous les membres de champ de ces structures provoquent un avertissement comme celui-ci: -

Le champ d'avertissement 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader' n'est jamais assigné à, et aura toujours sa valeur par défaut nulle

ou

Avertissement Le champ 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus' n'est jamais utilisé

Ceux-ci peuvent-ils être désactivés avec #pragma warning disable? Si tel est le cas, quels seraient les numéros d'erreur correspondants? Sinon, y a-t-il autre chose que je puisse faire? Gardez à l'esprit que je ne sais quoi faire pour ce fichier, il est important que je reçoive des avertissements comme ceux-ci provenant d'autres fichiers.

Éditer

Exemple de structure: -

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
}
AnthonyWJones
la source
Pouvez-vous montrer la déclaration de ces champs, ou plutôt la structure dans laquelle ils se trouvent? c'est à dire. Donne un exemple.
Lasse V.Karlsen
11
Si ce sont des définitions d'interopérabilité, vous devriez normalement vous [StructLayout(LayoutKind.Sequential)]assurer que la disposition de la mémoire est correcte (dans l'implémentation actuelle, ce sera même sans cet attribut, mais AFAIK ce n'est pas garanti). Si je me souviens bien, le compilateur C # détecte la présence de cet attribut et supprime automatiquement ces avertissements car il sait que les champs doivent être là pour l'interopérabilité. (Je pourrais me tromper à ce sujet, donc poster comme commentaire au lieu de réponse).
Greg Beech
@Greg: C'est une information utile que je vais étudier. Je préférerais que l'avertissement ne soit pas généré plutôt que de le supprimer.
AnthonyWJones
1
+1 pour l'utilisation StructLayout. Cela semble plus propre que de supprimer les avertissements eux-mêmes.
Deanna
@GregBeech Vous avez raison! Cela s'applique toujours aux projets .NET Standard sur VS2017.
zwcloud

Réponses:

195

Oui, ceux-ci peuvent être supprimés.

Normalement, je suis opposé à la suppression des avertissements, mais dans ce cas, les structures utilisées pour l'interopérabilité nécessitent absolument la présence de certains champs, même si vous n'avez jamais l'intention de (ou ne pouvez) les utiliser, donc dans ce cas, je pense que cela devrait être justifié .

Normalement, pour supprimer ces deux avertissements, vous corrigeriez le code incriminé. Le premier ("... n'est jamais utilisé") est généralement une odeur de code des restes de versions antérieures du code. Peut-être que le code a été supprimé, mais les champs sont laissés pour compte.

Le second est généralement une odeur de code pour les champs mal utilisés. Par exemple, vous pourriez écrire de manière incorrecte la nouvelle valeur d'une propriété dans la propriété elle-même, sans jamais écrire dans le champ de sauvegarde.


Pour supprimer les avertissements pour "Le champ XYZ n'est jamais utilisé ", procédez comme suit:

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

Pour supprimer les avertissements pour "Le champ XYZ n'est jamais attribué à et aura toujours sa valeur par défaut XX ", procédez comme suit:

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

Pour trouver vous-même de tels numéros d'avertissement (c'est-à-dire comment ai-je su utiliser 0169 et 0649), procédez comme suit:

  • Compilez le code normalement, cela ajoutera des avertissements à votre liste d'erreurs dans Visual Studio
  • Basculez vers la fenêtre Sortie et la sortie Build, et recherchez les mêmes avertissements
  • Copiez le code d'avertissement à 4 chiffres du message correspondant, qui devrait ressembler à ceci:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): avertissement CS 0649 : Le champ 'ConsoleApplication19.Program.dwReserved' n'est jamais affecté à et aura toujours sa valeur par défaut 0


Avertissement : selon le commentaire de @Jon Hanna , quelques avertissements sont peut-être nécessaires pour cela, pour les futurs chercheurs de cette question et réponse.

  • Tout d'abord, l'acte de supprimer un avertissement s'apparente à avaler des pilules pour les maux de tête. Bien sûr, c'est peut-être la bonne chose à faire parfois, mais ce n'est pas une solution fourre-tout. Parfois, un mal de tête est un vrai symptôme qu'il ne faut pas masquer, de même que les avertissements. Il est toujours préférable d'essayer de traiter les avertissements en corrigeant leur cause, au lieu de simplement les supprimer aveuglément de la sortie de construction.
  • Cela dit, si vous devez supprimer un avertissement, suivez le modèle que j'ai exposé ci-dessus. La première ligne de code #pragma warning disable XYZK,, désactive l'avertissement pour le reste de ce fichier , ou du moins jusqu'à ce qu'un correspondant #pragma warning restore XYZKsoit trouvé. Réduisez le nombre de lignes sur lesquelles vous désactivez ces avertissements. Le modèle ci-dessus désactive l'avertissement pour une seule ligne.
  • De plus, comme Jon le mentionne, un commentaire expliquant pourquoi vous faites cela est une bonne idée. La désactivation d'un avertissement est définitivement une odeur de code lorsqu'elle est effectuée sans cause, et un commentaire empêchera les futurs responsables de passer du temps à se demander pourquoi vous l'avez fait, ou même à le supprimer et à essayer de corriger les avertissements.
Lasse V. Karlsen
la source
9
Je recommanderais à la suite de la réponse ci-dessus, que la portée de la désactivation soit aussi petite que possible (pour éviter de la désactiver quelque part où elle est utile) et de toujours accompagner une désactivation d'un commentaire expliquant pourquoi vous désactivez, par exemple //exists for interopdans ce cas.
Jon Hanna du
Merci beaucoup. C'est un choix étrange que VS n'inclue pas de colonne pour ces nombres dans la fenêtre Liste d'erreurs.
AnthonyWJones
2
Comme le dit Jon, commenter le «pourquoi» est très important. De plus, j'ajoute généralement au moins une partie du texte du message d'avertissement au commentaire, par exemple // Suppress "n'est jamais assigné à ..." warning. Évitez aux futurs responsables de la maintenance de devoir rechercher le code d'avertissement - après tout, cela pourrait être vous!
Tom Bushell du
1
Ce n'est pas immédiatement évident, mais vous pouvez utiliser Rechercher dans la fenêtre Sortie via CTRL + F, tapez «avertissement», cliquez sur «Rechercher tout» et obtenez chaque avertissement rapidement, avec les numéros d'avertissement affichés. Cela dit, l' [StructLayout(LayoutKind.Sequential)]attribut gère beaucoup mieux l'interopérabilité, selon le commentaire de Greg Beech sur la question.
Ryan Buddicom
2
Commentant pour dire que pour les utilisateurs d'Unity3D, les numéros d'avertissement sont 0414 pour les champs privés et 0219 pour les variables locales, et non 169 (ce qui jette un avertissement sur l'impossibilité de restaurer l'avertissement à la place).
Draco18s ne fait plus confiance à SE
14

Une autre «solution» pour corriger ces avertissements consiste à créer la structure public. Les avertissements ne sont pas émis alors car le compilateur ne peut pas savoir si les champs sont utilisés (affectés) en dehors de l'assembly.

Cela dit, les composants «interop» ne devraient généralement pas être publics, mais plutôt internalou private.

floele
la source
2
Nice, ce ne cache l'avertissement ... mais la fixation d' un tel structcomme publicest d'être une erreur plus probable que la mise en garde que nous essayons de masquer. (Vous ne devriez probablement pas exposer inutilement les types utilisés pour l'implémentation interne et les types avec des champs publics n'appartiennent probablement pas à une API publique). Juste pour renforcer votre avis que ces types devraient être «plutôt internalou private» ;-).
binki
génial merci - c'est ce dont j'avais besoin. J'utilise JsonConvert.DeserializeObjectet je désérialise dans une classe publique qui a juste toutes les propriétés exposées afin que je sache ce qui sera retourné. Le simple fait d'en faire une classe publique vide avec toutes les chaînes publiques est un bon code court et maintenant plus d'avertissements. Peut-être que l'utilisation d'une classe dynamique serait mieux car vous n'avez pas à indiquer explicitement ce qu'il y a dans le tableau, mais je pense que ce sera une bonne référence pour quiconque espère utiliser l'objet.
user1274820
6

J'ai demandé à VS de générer le squelette d'implémentation pour System.ComponentModel.INotifyPropertyChangedet les événements ont été implémentés en tant que champs qui ont déclenché les avertissements CS0067.

Comme alternative à la solution donnée dans la réponse acceptée, j'ai converti les champs en propriétés et l'avertissement a disparu .

Cela a du sens puisque la syntaxe des déclarations de propriété Sugar est compilée dans un champ plus des méthodes getter et / ou setter (ajouter / supprimer dans mon cas) qui référencent le champ. Cela satisfait le compilateur et les avertissements ne sont pas déclenchés:

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
}
Pencho Ilchev
la source
Votre solution est bien plus simple que de désactiver l'avertissement, mais elle peut interférer avec certains attributs de champ uniquement, par exemple MarshalAsAttribute.
HuBeZa
1
Info: Les champs privés réels générés dans cette situation peuvent avoir des noms "étranges" tels que <GetHeader>k__BackingField, selon les détails d'implémentation du compilateur C # utilisé.
Jeppe Stig Nielsen
1

Les utilisateurs C / C ++ doivent (void)var;supprimer les avertissements de variables inutilisées. Je viens de découvrir que vous pouvez également supprimer les avertissements de variables inutilisées en C # avec des opérateurs au niveau du bit:

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

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

Les deux expressions ne produisent pas d'avertissements de variables inutilisées dans les compilateurs VS2010 C # 4.0 et Mono 2.10.

ceztko
la source
4
Fonctionne pour uint, mais pas pour les autres types, comme Exception. Connaissez-vous une astuce générique équivalente au C / C ++ var;?
manuell
1
@manuell bonjour du futur! Vous pouvez utiliser error.ToString();pour une variable de typeException
Sv443
Merci à partir de maintenant. Cette astuce ajoute du vrai code au moment de l'exécution, non?
manuell