Soppressione degli avvisi "non è mai usato" e "non è mai assegnato a" in C #


107

Ho un file HTTPSystemDefinitions.cs nel progetto C # che sostanzialmente descrive l'ISAPI di Windows precedente per l'utilizzo da parte del codice gestito.

Ciò include il set completo di strutture rilevanti per ISAPI non tutte o che vengono utilizzate dal codice. Durante la compilazione tutti i membri del campo di queste strutture causano un avviso come il seguente: -

Il campo di avviso "UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader" non è mai assegnato e avrà sempre il valore predefinito null

o

Attenzione Il campo 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus' non viene mai utilizzato

Possono essere disabilitati con #pragma warning disable? In caso affermativo, quali sarebbero i numeri di errore corrispondenti? In caso contrario, c'è qualcos'altro che posso fare? Tieni presente che ho solo cosa fare per questo file, è importante che riceva avvisi come questi provenienti da altri file.

modificare

Struttura di esempio: -

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
}

Puoi mostrare la dichiarazione di quei campi, o meglio, la struttura in cui si trovano? vale a dire. dare un esempio.
Lasse V. Karlsen,

11
Se queste sono definizioni di interoperabilità, normalmente dovresti [StructLayout(LayoutKind.Sequential)]assicurarti che il layout della memoria sia corretto (nell'attuale implementazione sarà anche senza questo attributo, ma AFAIK non è garantito). Se ricordo bene, il compilatore C # rileva la presenza di questo attributo e sopprime automaticamente tali avvisi poiché sa che i campi devono essere presenti per l'interoperabilità. (Potrei sbagliarmi su questo, quindi postare come commento invece che come risposta).
Greg Beech

@ Greg: Sono informazioni utili su cui indagherò, preferirei che l'avviso non venisse generato piuttosto che sopprimerli.
AnthonyWJones

1
+1 per l'utilizzo StructLayout. Sembra più pulito che sopprimere gli avvisi stessi.
Deanna

@GregBeech Hai ragione! Ciò vale ancora per i progetti .NET Standard su VS2017.
zwcloud

Risposte:


195

Sì, questi possono essere soppressi.

Normalmente sono contrario a sopprimere gli avvisi, ma in questo caso le strutture usate per l'interoperabilità richiedono assolutamente che alcuni campi siano presenti, anche se non si intende mai (o si può) usarli, quindi in questo caso penso che dovrebbe essere giustificato .

Normalmente, per sopprimere questi due avvisi, dovresti correggere il codice offensivo. Il primo ("... non viene mai usato") di solito è un odore di codice di avanzi delle versioni precedenti del codice. Forse il codice è stato eliminato, ma i campi sono rimasti indietro.

Il secondo è solitamente un odore di codice per i campi utilizzati in modo errato. Ad esempio, potresti riscrivere in modo errato il nuovo valore di una proprietà nella proprietà stessa, senza mai scrivere nel campo sottostante.


Per eliminare gli avvisi per "Il campo XYZ non viene mai utilizzato ", procedi come segue:

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

Per sopprimere gli avvisi per "Il campo XYZ non è mai assegnato e avrà sempre il suo valore predefinito XX ", procedi come segue:

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

Per trovare da soli tali numeri di avviso (ad es. Come facevo a sapere di usare 0169 e 0649), fai questo:

  • Compila il codice normalmente, questo aggiungerà alcuni avvisi all'elenco degli errori in Visual Studio
  • Passa alla finestra Output e all'output Build e cerca gli stessi avvisi
  • Copia il codice di avviso a 4 cifre dal messaggio pertinente, che dovrebbe assomigliare a questo:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): avviso CS 0649 : il campo 'ConsoleApplication19.Program.dwReserved' non è mai assegnato e avrà sempre il suo valore predefinito 0


Avvertenza : come da commento di @Jon Hanna , forse alcuni avvertimenti sono necessari per questo, per i futuri cercatori di questa domanda e risposta.

  • Innanzitutto, l'atto di sopprimere un avvertimento è simile a deglutire pillole per il mal di testa. Certo, a volte potrebbe essere la cosa giusta da fare, ma non è una soluzione universale. A volte, un mal di testa è un vero sintomo che non dovresti mascherare, lo stesso con gli avvertimenti. È sempre meglio cercare di trattare gli avvisi risolvendone la causa, invece di rimuoverli ciecamente dall'output di compilazione.
  • Detto questo, se hai bisogno di sopprimere un avvertimento, segui lo schema che ho esposto sopra. La prima riga di codice #pragma warning disable XYZK,, disabilita l'avviso per il resto di quel file , o almeno finché non #pragma warning restore XYZKviene trovato un corrispondente . Riduci al minimo il numero di righe su cui disabiliti questi avvisi. Il modello sopra disabilita l'avviso per una sola riga.
  • Inoltre, come dice Jon, un commento sul perché lo stai facendo è una buona idea. Disabilitare un avviso è sicuramente un odore di codice se fatto senza motivo, e un commento impedirà ai futuri manutentori di passare il tempo a chiedersi perché lo hai fatto, o anche rimuoverlo e provare a correggere gli avvisi.

9
Consiglierei oltre alla risposta sopra, che l'ambito della disabilitazione sia il più piccolo possibile (per evitare di disabilitarlo da qualche parte dove è utile) e di accompagnare sempre una disabilitazione con un commento sul motivo per cui stai disabilitando, ad esempio //exists for interopin questo caso.
Jon Hanna,

Molte grazie. È una strana scelta che VS non includa una colonna per questi numeri nella finestra Elenco errori.
AnthonyWJones

2
Come dice Jon, commentare il "perché" è molto importante. Inoltre, di solito aggiungo almeno una parte del testo del messaggio di avviso al commento, ad esempio // Sopprimi "non è mai assegnato a ..." avviso. Risparmia ai futuri manutentori il fastidio di dover cercare il codice di avviso - dopo tutto, potresti essere tu!
Tom Bushell,

1
Non è immediatamente ovvio, ma è possibile utilizzare Trova nella finestra di output tramite CTRL + F, digitare "avviso", fare clic su "Trova tutto" e ottenere rapidamente ogni avviso, con i numeri di avviso visualizzati. Detto questo, l' [StructLayout(LayoutKind.Sequential)]attributo gestisce l'interoperabilità molto meglio secondo il commento di Greg Beech sulla domanda.
Ryan Buddicom

2
Commentando per dire che per gli utenti di Unity3D, i numeri di avviso sono 0414 per i campi privati ​​e 0219 per le variabili locali, non 169 (che genera invece un avviso sull'impossibilità di ripristinare l'avviso).
Draco18s non si fida più di SE

14

Un'altra "soluzione" per correggere questi avvisi è creare la struttura public. Gli avvisi non vengono quindi emessi perché il compilatore non può sapere se i campi vengono utilizzati (assegnati) all'esterno dell'assembly.

Detto questo, i componenti di "interoperabilità" di solito non dovrebbero essere pubblici, ma piuttosto internalo private.


2
Bello, questo nasconde l'avviso ... ma l'impostazione di un structas publicè più probabile che sia un errore rispetto all'avviso che stiamo cercando di mascherare. (Probabilmente non dovresti esporre inutilmente i tipi utilizzati per l'implementazione interna e i tipi con campi pubblici probabilmente non appartengono a un'API pubblica). Solo per rafforzare il tuo consiglio che tali tipi dovrebbero essere "piuttosto internalo private" ;-).
binki

fantastico grazie - questo è ciò di cui avevo bisogno. Sto usando JsonConvert.DeserializeObjecte deserializzo in una classe pubblica che ha appena tutte le proprietà esposte in modo da sapere cosa verrà restituito. Il semplice fatto di renderla una classe pubblica vuota con tutte le stringhe pubbliche è un bel codice breve e ora non ci sono più avvisi. Forse usare una classe dinamica sarebbe meglio in quanto non è necessario dichiarare esplicitamente cosa c'è nell'array, ma penso che questo sarà un bel riferimento per chiunque speri di utilizzare l'oggetto.
user1274820

6

Ho ottenuto VS per generare lo scheletro di implementazione System.ComponentModel.INotifyPropertyChangede gli eventi sono stati implementati come campi che hanno attivato gli avvisi CS0067.

In alternativa alla soluzione data nella risposta accettata ho convertito i campi in proprietà e l'avviso è scomparso .

Ciò ha senso poiché la sintassi delle dichiarazioni di proprietà sugar viene compilata in un campo più metodi getter e / o setter (aggiungi / rimuovi nel mio caso) che fanno riferimento al campo. Questo soddisfa il compilatore e gli avvisi non vengono generati:

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
}

La tua soluzione è molto graziosa rispetto alla disabilitazione dell'avviso, ma potrebbe interferire con alcuni attributi solo di campo, ad esempio MarshalAsAttribute.
HuBeZa

1
Informazioni: i campi privati ​​effettivi generati in questa situazione potrebbero avere nomi "strani" come <GetHeader>k__BackingField, a seconda dei dettagli di implementazione del compilatore C # utilizzato.
Jeppe Stig Nielsen

1

Gli utenti C / C ++ devono (void)var;sopprimere gli avvisi di variabili inutilizzate. Ho appena scoperto che puoi anche sopprimere gli avvisi di variabili inutilizzate in C # con operatori bit per bit:

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

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

Entrambe le espressioni non producono avvisi di variabili inutilizzate nei compilatori VS2010 C # 4.0 e Mono 2.10.


4
Funziona per uint, ma non per altri tipi, come Exception. Conosci un trucco generico equivalente al C / C ++ var;?
manuell

1
@manuell ciao dal futuro! È possibile utilizzare error.ToString();per una variabile di tipoException
Sv443

Grazie da adesso. Quel trucco aggiunge codice reale in fase di esecuzione, giusto?
manuell
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.