Pomijanie ostrzeżeń „nigdy nie jest używane” i „nigdy nie jest przypisane” w języku C #

107

Mam plik HTTPSystemDefinitions.cs w projekcie C #, który zasadniczo opisuje starszy interfejs ISAPI systemu Windows do wykorzystania przez kod zarządzany.

Obejmuje to pełny zestaw struktur związanych z ISAPI, które nie są wszystkie lub które są wykorzystywane przez kod. Podczas kompilacji wszyscy członkowie pola tych struktur powodują ostrzeżenie podobne do następującego: -

Pole ostrzeżenia „UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader” nigdy nie jest przypisane do i zawsze będzie miało swoją domyślną wartość null

lub

Ostrzeżenie Pole „UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus” nigdy nie jest używane

Czy można je wyłączyć za pomocą #pragma warning disable ? Jeśli tak, jakie byłyby odpowiednie numery błędów? Jeśli nie, to czy mogę coś jeszcze zrobić? Pamiętaj, że ja tylko robię to dla tego pliku, ważne jest, żebym zobaczył ostrzeżenia takie jak te pochodzące z innych plików.

Edytować

Przykładowa struktura: -

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
źródło
Czy możesz pokazać deklarację tych pól, a raczej strukturę, w której się znajdują? to znaczy. daj przykład.
Lasse V. Karlsen
11
Jeśli są to definicje międzyoperacyjne, zwykle [StructLayout(LayoutKind.Sequential)]należy się upewnić, że układ pamięci jest poprawny (w obecnej implementacji będzie nawet bez tego atrybutu, ale AFAIK nie jest to gwarantowane). Jeśli dobrze pamiętam, kompilator C # wykrywa obecność tego atrybutu i automatycznie pomija te ostrzeżenia, ponieważ wie, że pola muszą być dostępne dla międzyoperacyjnej. (Mogę się mylić, dlatego piszę jako komentarz zamiast odpowiedzi).
Greg Beech
@Greg: To przydatne informacje, które zbadam Wolę raczej nie generować ostrzeżenia, niż je tłumić.
AnthonyWJones
1
+1 za używanie StructLayout. Wydaje się to czystsze niż tłumienie samych ostrzeżeń.
Deanna
@GregBeech Masz rację! To nadal dotyczy projektów .NET Standard w VS2017.
zwcloud

Odpowiedzi:

195

Tak, można je stłumić.

Zwykle sprzeciwiam się wygaszaniu ostrzeżeń, ale w tym przypadku struktury używane do interopu bezwzględnie wymagają obecności niektórych pól, nawet jeśli nigdy nie zamierzasz (lub nie możesz) ich używać, więc w tym przypadku myślę, że powinno to być uzasadnione .

Zwykle, aby usunąć te dwa ostrzeżenia, naprawiłbyś niewłaściwy kod. Pierwszy („… nigdy nie jest używany”) to zwykle zapach kodu pozostałości po wcześniejszych wersjach kodu. Być może kod został usunięty, ale pola pozostawione.

Drugi to zwykle zapach kodu dla nieprawidłowo używanych pól. Na przykład możesz niepoprawnie zapisać nową wartość właściwości z powrotem do samej właściwości, nigdy nie zapisując w polu zapasowym.


Aby wyłączyć ostrzeżenia „ Pole XYZ nigdy nie jest używane ”, wykonaj następujące czynności:

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

Aby pominąć ostrzeżenia dla „ Pola XYZ nigdy nie jest przypisane i zawsze będzie miało swoją domyślną wartość XX ”, wykonaj następujące czynności:

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

Aby samodzielnie znaleźć takie numery ostrzeżeń (tj. Skąd wiedziałem, że mam używać 0169 i 0649), wykonaj następujące czynności:

  • Skompiluj kod w normalny sposób, spowoduje to dodanie ostrzeżeń do listy błędów w programie Visual Studio
  • Przełącz się do okna Wyjście i wyjścia kompilacji i poszukaj tych samych ostrzeżeń
  • Skopiuj 4-cyfrowy kod ostrzegawczy z odpowiedniej wiadomości, który powinien wyglądać tak:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): ostrzeżenie CS 0649 : Pole „ConsoleApplication19.Program.dwReserved” nigdy nie jest przypisane do i zawsze będzie miało wartość domyślną 0


Uwaga : zgodnie z komentarzem @Jon Hanny , być może kilka ostrzeżeń jest na to potrzebne, dla przyszłych użytkowników tego pytania i odpowiedzi.

  • Po pierwsze i najważniejsze, powstrzymywanie ostrzeżenia jest podobne do połykania tabletek na ból głowy. Jasne, czasami może to być właściwe rozwiązanie, ale nie jest to uniwersalne rozwiązanie. Czasami ból głowy jest prawdziwym objawem, którego nie należy maskować, podobnie jak ostrzeżenia. Zawsze najlepiej jest spróbować leczyć ostrzeżenia, naprawiając ich przyczynę, zamiast po prostu usuwać je na ślepo z wyniku kompilacji.
  • Powiedziawszy to, jeśli chcesz usunąć ostrzeżenie, postępuj zgodnie ze schematem, który przedstawiłem powyżej. Pierwsza linia kodu #pragma warning disable XYZKwyłącza ostrzeżenie dla pozostałej części tego pliku lub przynajmniej do czasu #pragma warning restore XYZKznalezienia odpowiedniego. Zminimalizuj liczbę wierszy, w których wyłączasz te ostrzeżenia. Powyższy wzór wyłącza ostrzeżenie tylko dla jednej linii.
  • Ponadto, jak wspomina Jon, komentarz wyjaśniający, dlaczego to robisz, jest dobrym pomysłem. Wyłączenie ostrzeżenia jest zdecydowanie zapachem kodu, gdy jest wykonywane bez przyczyny, a komentarz uniemożliwi przyszłym opiekunom spędzanie czasu na zastanawianiu się, dlaczego to zrobiłeś, lub nawet na usunięciu go i próbie naprawienia ostrzeżeń.
Lasse V. Karlsen
źródło
9
Polecam dalej do odpowiedzi powyżej, że zakres wyłączenie być jak najmniejsza (aby uniknąć uszkodzenia go gdzieś, gdzie jest to przydatne) i zawsze towarzyszyć wyłączenie z komentarzem, dlaczego jesteś wyłączanie, np //exists for interopw ta sprawa.
Jon Hanna,
Wielkie dzięki. To dziwny wybór, że VS nie zawiera kolumny dla tych liczb w oknie Lista błędów.
AnthonyWJones,
2
Jak mówi Jon, komentowanie „dlaczego” jest bardzo ważne. Dodatkowo zazwyczaj przynajmniej część tekstu ostrzeżenia dodaję do komentarza, np. // Suppress Ostrzeżenie „nigdy nie jest przypisane do…”. Oszczędź przyszłym opiekunom irytacji związanej z koniecznością wyszukiwania kodu ostrzegawczego - w końcu możesz to być Ty!
Tom Bushell
1
Nie jest to od razu oczywiste, ale możesz użyć Znajdź w oknie Wyjście przez CTRL + F, wpisać „ostrzeżenie”, kliknąć „Znajdź wszystko” i szybko uzyskać każde ostrzeżenie z wyświetlonymi numerami ostrzeżeń. To powiedziawszy, że obsługa [StructLayout(LayoutKind.Sequential)]atrybutu znacznie lepiej współdziała, zgodnie z komentarzem Grega Beecha do pytania.
Ryan Buddicom
2
Komentując, że dla użytkowników Unity3D numery ostrzeżeń to 0414 dla pól prywatnych i 0219 dla zmiennych lokalnych, a nie 169 (co powoduje wyświetlenie ostrzeżenia o niemożności przywrócenia ostrzeżenia).
Draco18s nie ufa już SE
14

Innym „rozwiązaniem” naprawienia tych ostrzeżeń jest utworzenie struktury public. Ostrzeżenia nie są wtedy generowane, ponieważ kompilator nie może wiedzieć, czy pola są używane (przypisywane) poza zestawem.

To powiedziawszy, komponenty „interop” zwykle nie powinny być publiczne, ale raczej internallub private.

floele
źródło
2
Fajnie, to ukrywa ostrzeżenie… ale ustawienie takiego structznaku publicjest bardziej prawdopodobne, że będzie błędem niż ostrzeżenie, które próbujemy zamaskować. (Prawdopodobnie nie powinieneś niepotrzebnie ujawniać typów używanych do wewnętrznej implementacji, a typy z polami publicznymi prawdopodobnie nie należą do publicznego interfejsu API). Żeby tylko wzmocnić twoją radę, że takie typy powinny być „raczej internallub private” ;-).
binki
super dzięki - tego potrzebowałem. Używam JsonConvert.DeserializeObjecti deserializuję do klasy publicznej, która ma tylko wszystkie ujawnione właściwości, dzięki czemu wiem, co zostanie zwrócone. Samo uczynienie z niej klasy publicznej, która jest pusta ze wszystkimi publicznymi ciągami, jest fajnym, krótkim kodem i nie ma już więcej ostrzeżeń. Być może użycie klasy dynamicznej byłoby lepsze, ponieważ nie musisz jawnie określać, co jest w tablicy, ale myślę, że będzie to dobre odniesienie dla każdego, kto chce użyć obiektu.
user1274820
6

Dostałem VS do wygenerowania szkieletu implementacji dla System.ComponentModel.INotifyPropertyChangedi zdarzenia zostały zaimplementowane jako pola, które wyzwoliły ostrzeżenia CS0067.

Zamiast rozwiązania podanego w zaakceptowanej odpowiedzi zamieniłem pola na właściwości i ostrzeżenie zniknęło .

Ma to sens, ponieważ cukier składni deklaracji właściwości jest kompilowany do pola plus metody pobierające i / lub ustawiające (w moim przypadku dodaj / usuń), które odwołują się do pola. To spełnia wymagania kompilatora, a ostrzeżenia nie są zgłaszane:

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
źródło
Twoje rozwiązanie jest dużo wdzięczne niż wyłączenie ostrzeżenia, ale może kolidować z niektórymi atrybutami tylko dla pól, np. MarshalAsAttribute.
HuBeZa
1
Informacje: Rzeczywiste pola prywatne wygenerowane w tej sytuacji mogą mieć „dziwne” nazwy, takie jak <GetHeader>k__BackingFieldw zależności od szczegółów implementacji używanego kompilatora C #.
Jeppe Stig Nielsen
1

Użytkownicy C / C ++ muszą (void)var;pomijać ostrzeżenia o nieużywanych zmiennych. Właśnie odkryłem, że możesz również pomijać ostrzeżenia o nieużywanych zmiennych w C # za pomocą operatorów bitowych:

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

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

Oba wyrażenia nie generują nieużywanych ostrzeżeń o zmiennych w kompilatorach VS2010 C # 4,0 i Mono 2,10.

ceztko
źródło
4
Działa w uintprzypadku innych typów plików, takich jak Exception. Czy znasz ogólny trik będący odpowiednikiem C / C ++ var;?
manuell
1
@manuell witaj z przyszłości! Możesz użyć error.ToString();dla zmiennej typuException
Sv443
Dzięki od teraz. Ta sztuczka dodaje prawdziwy kod w czasie wykonywania, prawda?
manuell