Das Unterdrücken der Warnungen "wird nie verwendet" und "wird nie zugewiesen" in C #

107

Ich habe eine HTTPSystemDefinitions.cs-Datei im C # -Projekt, die im Grunde die älteren Windows-ISAPI für den Verbrauch durch verwalteten Code beschreibt.

Dies umfasst den vollständigen Satz von Strukturen, die für die ISAPI relevant sind, nicht alle oder die vom Code verbraucht werden. Bei der Kompilierung verursachen alle Feldmitglieder dieser Strukturen eine Warnung wie die folgende: -

Das Warnfeld 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader' wird niemals zugewiesen und hat immer den Standardwert null

oder

Warnung Das Feld 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus' wird niemals verwendet

Können diese mit deaktiviert werden #pragma warning disable? Wenn ja, wie lauten die entsprechenden Fehlernummern? Wenn nicht, kann ich noch etwas tun? Denken Sie daran, dass ich nur weiß, was ich für diese Datei tun soll. Es ist wichtig, dass ich Warnungen wie diese aus anderen Dateien sehe.

Bearbeiten

Beispielstruktur: -

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
quelle
Können Sie die Deklaration dieser Felder oder vielmehr die Struktur anzeigen, in der sie sich befinden? dh. gib ein Beispiel.
Lasse V. Karlsen
11
Wenn es sich um Interop-Definitionen handelt, sollten Sie normalerweise [StructLayout(LayoutKind.Sequential)]sicherstellen, dass das Speicherlayout korrekt ist (in der aktuellen Implementierung ist es sogar ohne dieses Attribut, aber AFAIK ist nicht garantiert). Wenn ich mich richtig erinnere, erkennt der C # -Compiler das Vorhandensein dieses Attributs und unterdrückt diese Warnungen automatisch, da er weiß, dass Felder für die Interop vorhanden sein müssen. (Ich könnte mich irren und daher als Kommentar statt als Antwort posten).
Greg Beech
@ Greg: Das sind nützliche Informationen, die ich untersuchen werde. Ich möchte lieber, dass die Warnung nicht generiert wird, als sie zu unterdrücken.
AnthonyWJones
1
+1 für die Verwendung StructLayout. Es scheint sauberer zu sein, als die Warnungen selbst zu unterdrücken.
Deanna
@ GregBeech Du hast recht! Dies gilt weiterhin für .NET Standard-Projekte unter VS2017.
Zwcloud

Antworten:

195

Ja, diese können unterdrückt werden.

Normalerweise bin ich gegen die Unterdrückung von Warnungen, aber in diesem Fall müssen für Interop-Strukturen unbedingt einige Felder vorhanden sein, auch wenn Sie diese niemals verwenden möchten (oder können). In diesem Fall sollte dies meiner Meinung nach gerechtfertigt sein .

Um diese beiden Warnungen zu unterdrücken, würden Sie normalerweise den fehlerhaften Code korrigieren. Das erste ("... wird nie verwendet") ist normalerweise ein Code-Geruch von Resten aus früheren Versionen des Codes. Möglicherweise wurde Code gelöscht, aber Felder zurückgelassen.

Der zweite ist normalerweise ein Code-Geruch für falsch verwendete Felder. Beispielsweise können Sie den neuen Wert einer Eigenschaft fälschlicherweise in die Eigenschaft selbst zurückschreiben und niemals in das Hintergrundfeld schreiben.


Gehen Sie folgendermaßen vor, um Warnungen für " Feld XYZ wird niemals verwendet " zu unterdrücken :

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

Um Warnungen für " Feld XYZ ist niemals zugewiesen und hat immer den Standardwert XX " zu unterdrücken , gehen Sie folgendermaßen vor:

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

Um solche Warnnummern selbst zu finden (dh woher wusste ich, dass 0169 und 0649 verwendet werden), gehen Sie folgendermaßen vor:

  • Kompilieren Sie den Code wie gewohnt. Dadurch werden einige Warnungen zu Ihrer Fehlerliste in Visual Studio hinzugefügt
  • Wechseln Sie zum Ausgabefenster und zur Build-Ausgabe und suchen Sie nach denselben Warnungen
  • Kopieren Sie den 4-stelligen Warncode aus der entsprechenden Nachricht, die folgendermaßen aussehen sollte:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): Warnung CS 0649 : Das Feld 'ConsoleApplication19.Program.dwReserved' wird niemals zugewiesen und hat immer den Standardwert 0


Vorsichtsmaßnahme : Laut dem Kommentar von @Jon Hanna sind möglicherweise einige Warnungen angebracht, damit zukünftige Finder dieser Frage und Antwort.

  • In erster Linie ist das Unterdrücken einer Warnung mit dem Schlucken von Tabletten gegen Kopfschmerzen vergleichbar. Sicher, es ist manchmal das Richtige, aber es ist keine umfassende Lösung. Manchmal sind Kopfschmerzen ein echtes Symptom, das Sie nicht maskieren sollten, ebenso wie Warnungen. Es ist immer am besten, die Warnungen zu behandeln, indem Sie ihre Ursache beheben, anstatt sie nur blind aus der Build-Ausgabe zu entfernen.
  • Wenn Sie jedoch eine Warnung unterdrücken müssen, folgen Sie dem oben beschriebenen Muster. Die erste Codezeile #pragma warning disable XYZKdeaktiviert die Warnung für den Rest dieser Datei oder zumindest bis eine entsprechende #pragma warning restore XYZKgefunden wird. Minimieren Sie die Anzahl der Zeilen, in denen Sie diese Warnungen deaktivieren. Das obige Muster deaktiviert die Warnung für nur eine Zeile.
  • Wie Jon erwähnt, ist ein Kommentar, warum Sie dies tun, eine gute Idee. Das Deaktivieren einer Warnung ist definitiv ein Code-Geruch, wenn sie ohne Grund ausgeführt wird. Ein Kommentar verhindert, dass zukünftige Betreuer Zeit damit verbringen, sich zu fragen, warum Sie sie ausgeführt haben, oder sie sogar zu entfernen und zu versuchen, die Warnungen zu beheben.
Lasse V. Karlsen
quelle
9
Ich würde auf die Antwort empfehle vor, dass der Umfang der Sperrung so klein wie möglich sein (zu vermeiden , ist es irgendwo zu deaktivieren , wo es sinnvoll ist) und immer eine Deaktivierung mit einem Kommentar begleitet, warum Sie zu deaktivieren, zum Beispiel //exists for interopin dieser Fall.
Jon Hanna
Vielen Dank. Es ist eine seltsame Wahl, dass VS keine Spalte für diese Nummern im Fehlerlistenfenster enthält.
AnthonyWJones
2
Wie Jon sagt, ist es sehr wichtig, das "Warum" zu kommentieren. Außerdem füge ich normalerweise mindestens einen Teil des Textes der Warnmeldung zum Kommentar hinzu, z. B. // Unterdrückung "wird niemals zugewiesen ..." Warnung. Sparen Sie zukünftigen Betreuern den Ärger, den Warncode nachschlagen zu müssen - schließlich könnten Sie es sein!
Tom Bushell
1
Es ist nicht sofort offensichtlich, aber Sie können Suchen im Ausgabefenster über STRG + F verwenden, "Warnung" eingeben, auf "Alle suchen" klicken und jede Warnung schnell erhalten, wobei Warnnummern angezeigt werden. Das heißt, das [StructLayout(LayoutKind.Sequential)]Attribut handhabt Interop viel besser als in Greg Beechs Kommentar zu der Frage.
Ryan Buddicom
2
In einem Kommentar heißt es, dass für Unity3D-Benutzer die Warnnummern 0414 für private Felder und 0219 für lokale Variablen und nicht 169 sind (was eine Warnung auslöst, dass die Warnung nicht wiederhergestellt werden kann).
Draco18s vertraut SE
14

Eine andere "Lösung", um diese Warnungen zu beheben, besteht darin, die Struktur zu erstellen public. Die Warnungen werden dann nicht ausgegeben, da der Compiler nicht wissen kann, ob die Felder außerhalb der Assembly verwendet (zugewiesen) werden.

Das heißt, "Interop" -Komponenten sollten normalerweise nicht öffentlich sein, sondern internaloder private.

floele
quelle
2
Nizza, tut dies verstecken die Warnung ... aber Einstellung so ein , structwie publicwahrscheinlicher ist ein Fehler , als die Warnung, die wir zu verschleiern versuchen. (Sie sollten wahrscheinlich nicht unnötig Typen verfügbar machen, die für die interne Implementierung verwendet werden, und Typen mit öffentlichen Feldern gehören wahrscheinlich nicht in eine öffentliche API.) Nur um Ihren Rat zu bekräftigen, dass solche Typen "eher internaloder private" sein sollten ;-).
Binki
super danke - das habe ich gebraucht. Ich verwende JsonConvert.DeserializeObjectund deserialisiere in eine öffentliche Klasse, in der nur alle Eigenschaften verfügbar sind, damit ich weiß, was zurückgegeben wird. Nur eine öffentliche Klasse zu machen, die mit allen öffentlichen Zeichenfolgen leer ist, ist ein netter Funktionscode und jetzt keine Warnungen mehr. Vielleicht wäre die Verwendung einer dynamischen Klasse besser, da Sie nicht explizit angeben müssen, was sich im Array befindet, aber ich denke, dies ist eine gute Referenz für alle, die das Objekt verwenden möchten.
user1274820
6

Ich habe VS beauftragt, das Implementierungsskelett für zu generieren, System.ComponentModel.INotifyPropertyChangedund die Ereignisse wurden als Felder implementiert, die die CS0067-Warnungen auslösten.

Als Alternative zu der in der akzeptierten Antwort angegebenen Lösung habe ich die Felder in Eigenschaften konvertiert und die Warnung ist verschwunden .

Dies ist sinnvoll, da die Syntaxzucker für Eigenschaftsdeklarationen in ein Feld plus Getter- und / oder Setter-Methoden (in meinem Fall Hinzufügen / Entfernen) kompiliert werden, die auf das Feld verweisen. Dies erfüllt den Compiler und die Warnungen werden nicht ausgegeben:

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
quelle
Ihre Lösung ist viel eleganter als das Deaktivieren der Warnung, kann jedoch einige Nur-Feld-Attribute beeinträchtigen, z. B. MarshalAsAttribute.
HuBeZa
1
Info: Die in dieser Situation tatsächlich generierten privaten Felder können "seltsame" Namen haben, z. B. <GetHeader>k__BackingFieldabhängig von den Implementierungsdetails des verwendeten C # -Compilers.
Jeppe Stig Nielsen
1

C / C ++ - Benutzer müssen (void)var;Warnungen vor nicht verwendeten Variablen unterdrücken. Ich habe gerade festgestellt, dass Sie Warnungen für nicht verwendete Variablen in C # auch mit bitweisen Operatoren unterdrücken können:

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

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

Beide Ausdrücke erzeugen in VS2010 C # 4.0- und Mono 2.10-Compilern keine nicht verwendeten Variablenwarnungen.

ceztko
quelle
4
Funktioniert für uint, aber nicht für andere Typen, wie Exception. Kennen Sie einen generischen Trick, der C / C ++ entspricht var;?
manuell
1
@ Manuell Hallo aus der Zukunft! Sie können error.ToString();für eine Variable vom Typ verwendenException
Sv443
Danke von jetzt an. Dieser Trick fügt zur Laufzeit echten Code hinzu, oder?
manuell