Придушення попереджень "ніколи не використовується" та "ніколи не призначено" попереджень у C #


107

У мене є проект HTTPSystemDefinitions.cs у проекті C #, який в основному описує старіші програми Windows ISAPI для споживання керованим кодом.

Сюди входить повний набір структур, що стосуються ISAPI, не всі або які використовуються кодом. Під час компіляції всі польові члени цих структур викликають попередження на зразок наступного: -

Поле попередження 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader' ніколи не призначається, і завжди матиме значення за замовчуванням

або

Попередження Поле "UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus" ніколи не використовується

Чи можна їх відключити #pragma warning disable? Якщо так, якими були б відповідні номери помилок? Якщо ні, чи можна ще щось зробити? Майте на увазі, що я лише що робити для цього файлу, важливо, щоб я бачив попередження, подібні цим, з інших файлів.

Редагувати

Приклад структури: -

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
}

Чи можете ви показати декларацію цих полів, а точніше структуру, в якій вони знаходяться? тобто. наведіть приклад.
Лассе В. Карлсен

11
Якщо це визначення interop, то зазвичай ви хочете [StructLayout(LayoutKind.Sequential)]переконатися, що компонування пам'яті правильне (у поточній реалізації це буде навіть без цього атрибуту, але AFAIK це не гарантується). Якщо я добре пам’ятаю, компілятор C # виявляє наявність цього атрибута і автоматично пригнічує ці попередження, оскільки він знає, що поля повинні бути там для інтеропу. (Я можу помилитися з цього приводу, отже, розміщуючи коментар замість відповіді).
Грег Бук

@Greg: Це корисна інформація, яку я вивчу, я б скоріше не створював попередження, а не придушував їх.
AnthonyWJones

1
+1 для використання StructLayout. Це здається чистішим, ніж придушення самих попереджень.
Діана

@GregBeech Ви маєте рацію! Це все ще стосується проектів .NET Standard на VS2017.
zwcloud

Відповіді:


195

Так, це можна придушити.

Як правило, я проти придушення попереджень, але в цьому випадку для використовуваних конструкцій для інтеропа абсолютно необхідні деякі поля, хоча ви ніколи не збираєтесь (або можете) їх використовувати, тому в цьому випадку я думаю, що це повинно бути виправданим .

Зазвичай, щоб придушити ці два попередження, ви виправите код, що порушує. Перший ("... ніколи не використовується"), як правило, кодовий запах залишків з попередніх версій коду. Можливо, код було видалено, але поля залишилися позаду.

Другий, як правило, кодовий запах для неправильно використаних полів. Наприклад, ви можете неправильно записати нове значення властивості назад у власність, ніколи не записуючи у поле резервного копіювання.


Щоб придушити попередження для " Поле XYZ ніколи не використовується ", виконайте це:

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

Щоб придушити попередження " Поле XYZ ніколи не призначається, і завжди матиме значення за замовчуванням XX ", виконайте це:

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

Щоб самостійно знайти такі попереджувальні номери (тобто, як я знав, щоб використовувати 0169 та 0649), зробіть це:

  • Складіть код як звичайний, це додасть попередження до списку помилок у Visual Studio
  • Перейдіть у вікно "Вихід" та "Вивести збірку", і полюйте на ті самі попередження
  • Скопіюйте чотиризначний код попередження із відповідного повідомлення, яке має виглядати так:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): попередження CS 0649 : Поле "ConsoleApplication19.Program.dwReserved" ніколи не призначається і завжди матиме значення за замовчуванням 0


Caveat : Відповідно до коментаря @Jon Hanna , можливо, кілька попереджень є для цього для майбутніх шукачів цього питання та відповіді.

  • По-перше, і головне, акт придушення попередження схожий на ковтання таблеток від головного болю. Звичайно, іноді це може бути правильним, але це не загальне рішення. Іноді головний біль - це справжній симптом, який не слід маскувати, як і попередження. Завжди найкраще спробувати поводитися з попередженнями, виправляючи їх причину, а не просто сліпо видаляючи їх з виводу збірки.
  • Сказавши, що, якщо вам потрібно придушити попередження, дотримуйтесь шаблону, який я виклав вище. Перший рядок коду #pragma warning disable XYZK, відключає попередження для решти цього файлу або, принаймні, поки не #pragma warning restore XYZKбуде знайдено відповідне . Мінімізуйте кількість рядків, на яких виключаєте ці попередження. Вищевказана схема вимикає попередження лише для одного рядка.
  • Також, як згадує Джон, коментар щодо того, чому ти робиш це, є хорошою ідеєю. Вимкнення попередження, безумовно, має запах коду, коли робиться без причин, і коментар заважатиме майбутнім обслуговуючим особам витрачати час або на запитання, чому ви це зробили, або навіть видаляючи його і намагаючись виправити попередження.

9
Я б рекомендував додатково до відповіді вище, щоб сфера вимкнення була якомога меншою (щоб уникнути її відключення десь там, де це корисно), а також завжди супроводжувати відключення коментарем щодо того, чому ви відключаєте, наприклад, //exists for interopу цей випадок.
Джон Ханна

Дуже дякую. Дивний вибір: VS не містить стовпчик для цих чисел у вікні списку помилок.
AnthonyWJones

2
Як каже Джон, коментувати "чому" дуже важливо. Крім того, я зазвичай додаю принаймні частину тексту попереджувального повідомлення до коментаря, наприклад // Перевірка "ніколи не призначається ...". Збережіть майбутніх утримувачів роздратування від необхідності шукати попереджувальний код - адже це ви можете!
Том Бушелл

1
Це не відразу очевидно, але ви можете використовувати Знайти у вікні виводу за допомогою CTRL + F, введіть "попередження", натисніть "Знайти все" і швидко отримуйте кожне попередження, на якому відображаються номери попередження. Це сказало, що [StructLayout(LayoutKind.Sequential)]атрибут обробляє інтероп набагато краще, як це пояснює коментар Грега Бука.
Райан Буддіком

2
Коментуючи, що для користувачів Unity3D номери попередження становлять 0414 для приватних полів та 0219 для локальних змінних, а не 169 (що замість цього видає попередження про неможливість відновлення попередження).
Draco18s більше не довіряє SE

14

Ще одне "рішення" виправити ці попередження - це зробити структура public. Тоді попередження не видаються, тому що компілятор не може знати, використовуються чи призначаються поля поза монтажем.

Тим НЕ менше, «Interop» компоненти повинні , як правило , не публічно, а internalчи private.


2
Приємно, це приховує попередження… але встановлення такого типу struct, publicшвидше за все, буде помилкою, ніж попередження, яке ми намагаємось замаскувати. (Напевно, вам не слід надмірно виставляти типи, що використовуються для внутрішньої реалізації, а типи з публічними полями, ймовірно, не належать до загальнодоступного API). Просто на підтвердження вашої ради, що такі типи повинні бути «скоріше internalабо private» ;-).
бінкі

дивовижна подяка - це те, що мені було потрібно. Я використовую, JsonConvert.DeserializeObjectі я десеріалізуюсь у публічному класі, який просто має всі властивості, так що я знаю, що буде повернено. Просто зробити його публічним класом, який порожній з усіма публічними рядками - це хороший короткий код і тепер більше немає попереджень. Можливо, використання динамічного класу було б краще, оскільки вам не доведеться чітко вказувати, що є в масиві, але я думаю, що це буде хорошим посиланням для тих, хто сподівається використати об’єкт.
користувач1274820

6

У мене з'явився VS для створення скелета реалізації, System.ComponentModel.INotifyPropertyChangedі події були реалізовані у вигляді полів, які викликали попередження CS0067.

Як альтернатива рішенню, наведеному у прийнятій відповіді, я перетворив поля у властивості, і попередження зникло .

Це має сенс, оскільки синтаксис цукру синтаксису декларацій властивості компілюється в поле плюс методи getter та / або setter (додавання / видалення в моєму випадку), на яке посилається поле. Це задовольняє компілятора, і попередження не підвищуються:

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
}

Ваше рішення набагато витонченіше, ніж вимкнення попередження, але воно може заважати деяким атрибутам, що стосуються лише поля, наприклад, MarshalAsAttribute.
HuBeZa

1
Інформація: Фактичні приватні поля, що генеруються в цій ситуації, можуть мати "дивні" назви, такі як <GetHeader>k__BackingField, залежно від деталей реалізації використовуваного компілятора C #.
Джеппе Стіг Нільсен

1

Користувачі C / C ++ повинні (void)var;придушувати попередження про невикористані змінні. Щойно я виявив, що ви також можете придушити попередження про невикористані змінні в C # за допомогою побітових операторів:

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

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

Обидва вирази не створюють невикористаних попереджень змінних у компіляторах VS2010 C # 4.0 та Mono 2.10.


4
Працює uint, але не для інших типів, як Exception. Чи знаєте ви загальний трюк, еквівалентний C / C ++ var;?
manuell

1
@manuell привіт від майбутнього! Ви можете використовувати error.ToString();для змінної типуException
Sv443

Дякую відтепер Цей трюк додає реальний код під час виконання, так?
manuell
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.