Loại bỏ cảnh báo "không bao giờ được sử dụng" và "không bao giờ được gán cho" trong C #


107

Tôi có tệp HTTPSystemDefinitions.cs trong dự án C # mô tả về cơ bản ISAPI cửa sổ cũ hơn để sử dụng bằng mã được quản lý.

Điều này bao gồm toàn bộ các Cấu trúc có liên quan đến ISAPI, không phải tất cả hoặc được sử dụng bởi mã. Khi biên dịch, tất cả các thành viên trường của các cấu trúc này gây ra cảnh báo như sau: -

Trường Cảnh báo 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.SetHeader' không bao giờ được gán cho và sẽ luôn có giá trị mặc định là rỗng

hoặc là

Cảnh báo Trường 'UnionSquare.ISAPI.HTTP_FILTER_PREPROC_HEADERS.HttpStatus' không bao giờ được sử dụng

Có thể tắt những điều này với #pragma warning disable? Nếu vậy các số lỗi tương ứng sẽ là bao nhiêu? Nếu không, tôi có thể làm gì khác? Hãy nhớ rằng tôi chỉ làm điều này cho tệp này, điều quan trọng là tôi nhận được các cảnh báo như thế này đến từ các tệp khác.

Biên tập

Cấu trúc ví dụ: -

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
}

Bạn có thể hiển thị phần khai báo của các trường đó, hay đúng hơn là cấu trúc của chúng không? I E. cho một ví dụ.
Lasse V. Karlsen

11
Nếu đây là các định nghĩa tương tác, thì thông thường bạn phải đặt [StructLayout(LayoutKind.Sequential)]để đảm bảo bố cục bộ nhớ là chính xác (trong triển khai hiện tại, nó sẽ thậm chí không có thuộc tính này, nhưng AFAIK thì nó không được đảm bảo). Nếu tôi nhớ không nhầm, trình biên dịch C # phát hiện sự hiện diện của thuộc tính này và tự động loại bỏ các cảnh báo đó vì nó biết các trường phải ở đó để tương tác. (Tôi có thể sai về điều này, do đó đăng dưới dạng bình luận thay vì câu trả lời).
Greg Beech

@Greg: Đó là thông tin hữu ích mà tôi sẽ điều tra Tôi không muốn cảnh báo được tạo ra hơn là ngăn chặn chúng.
AnthonyWJones

1
+1 để sử dụng StructLayout. Nó có vẻ rõ ràng hơn là tự ngăn chặn các cảnh báo.
Deanna

@GregBboards Bạn nói đúng! Điều đó vẫn áp dụng cho các dự án .NET Standard trên VS2017.
zwcloud

Câu trả lời:


195

Có, những thứ này có thể bị đàn áp.

Thông thường, tôi phản đối việc loại bỏ các cảnh báo, nhưng trong trường hợp này, các cấu trúc được sử dụng cho tương tác hoàn toàn yêu cầu một số trường phải có mặt, mặc dù bạn không bao giờ có ý định (hoặc có thể) sử dụng chúng, vì vậy trong trường hợp này, tôi nghĩ nó nên hợp lý .

Thông thường, để ngăn chặn hai cảnh báo đó, bạn sẽ sửa mã vi phạm. Đầu tiên ("... không bao giờ được sử dụng") thường là mùi mã của thức ăn thừa từ các phiên bản mã trước đó. Có lẽ mã đã bị xóa, nhưng các trường vẫn còn sót lại.

Thứ hai thường là mùi mã cho các trường được sử dụng không chính xác. Ví dụ: bạn có thể ghi sai giá trị mới của một thuộc tính vào lại chính thuộc tính đó, không bao giờ ghi vào trường sao lưu.


Để loại bỏ cảnh báo " Trường XYZ không bao giờ được sử dụng ", bạn làm như sau:

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

Để loại bỏ cảnh báo cho " Trường XYZ không bao giờ được gán cho và sẽ luôn có giá trị mặc định của nó là XX ", bạn làm như sau:

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

Để tự tìm các số cảnh báo như vậy (tức là làm sao tôi biết sử dụng 0169 và 0649), bạn làm như sau:

  • Biên dịch mã như bình thường, điều này sẽ thêm một số cảnh báo vào danh sách lỗi của bạn trong Visual Studio
  • Chuyển sang cửa sổ Đầu ra và đầu ra Xây dựng, và tìm kiếm các cảnh báo tương tự
  • Sao chép mã cảnh báo gồm 4 chữ số từ thông báo có liên quan, mã này sẽ giống như sau:

    C: \ Dev \ VS.NET \ ConsoleApplication19 \ ConsoleApplication19 \ Program.cs (10,28): warning CS 0649 : Trường 'ConsoleApplication19.Program.dwReserved' không bao giờ được gán cho và sẽ luôn có giá trị mặc định là 0


Lưu ý : Theo nhận xét của @Jon Hanna , có lẽ một vài cảnh báo dành cho điều này, cho những người tìm ra câu hỏi và câu trả lời này trong tương lai.

  • Đầu tiên, và quan trọng nhất, hành động ngăn chặn cảnh báo cũng giống như việc nuốt thuốc giảm đau đầu. Chắc chắn, đôi khi nó có thể là điều đúng đắn, nhưng nó không phải là một giải pháp tổng thể. Đôi khi, đau đầu là một triệu chứng thực sự mà bạn không nên che giấu, cùng với các cảnh báo. Tốt nhất là luôn cố gắng xử lý các cảnh báo bằng cách sửa chữa nguyên nhân của chúng, thay vì chỉ xóa chúng khỏi đầu ra bản dựng một cách mù quáng.
  • Phải nói rằng, nếu bạn cần ngăn chặn một cảnh báo, hãy làm theo mô hình tôi đã trình bày ở trên. Dòng mã đầu tiên #pragma warning disable XYZK, vô hiệu hóa cảnh báo cho phần còn lại của tệp đó hoặc ít nhất là cho đến khi #pragma warning restore XYZKtìm thấy đoạn mã tương ứng . Giảm thiểu số dòng bạn tắt các cảnh báo này. Mẫu trên sẽ vô hiệu cảnh báo chỉ một dòng.
  • Ngoài ra, như Jon đã đề cập, một nhận xét về lý do tại sao bạn làm điều này là một ý kiến ​​hay. Việc vô hiệu hóa một cảnh báo chắc chắn là có mùi mã khi được thực hiện mà không có nguyên nhân và một nhận xét sẽ ngăn cản những người bảo trì trong tương lai dành thời gian tự hỏi tại sao bạn lại làm vậy, hoặc thậm chí bằng cách xóa nó và cố gắng sửa các cảnh báo.

9
Tôi khuyên bạn nên thêm cho câu trả lời ở trên, rằng phạm vi là vô hiệu hóa được càng nhỏ càng tốt (để tránh việc vô hiệu hóa nó ở đâu đó nơi nó rất hữu ích) và luôn luôn đi cùng một việc vô hiệu hóa với một bình luận là tại sao bạn đang vô hiệu hóa, ví dụ như //exists for interoptrong trường hợp này.
Jon Hanna

Cảm ơn rất nhiều. Một lựa chọn kỳ lạ là VS không bao gồm một cột cho những con số này trong cửa sổ Danh sách lỗi.
AnthonyWJones

2
Như Jon nói, bình luận "tại sao" là rất quan trọng. Ngoài ra, tôi thường thêm ít nhất một phần văn bản của thông báo cảnh báo vào nhận xét, ví dụ: // Suppress "không bao giờ được gán cho ..." cảnh báo. Tiết kiệm cho những người bảo trì trong tương lai sự phiền toái khi phải tra cứu mã cảnh báo - sau cùng, đó có thể là bạn!
Tom Bushell

1
Nó không rõ ràng ngay lập tức nhưng bạn có thể sử dụng Tìm trong cửa sổ Đầu ra thông qua CTRL + F, nhập "cảnh báo", nhấp vào "Tìm Tất cả" và nhận mọi cảnh báo một cách nhanh chóng, với số cảnh báo được hiển thị. Điều đó nói rằng [StructLayout(LayoutKind.Sequential)]thuộc tính xử lý tương tác tốt hơn nhiều theo nhận xét của Greg Beech về câu hỏi.
Ryan Buddicom

2
Nhận xét rằng đối với người dùng Unity3D, số cảnh báo là 0414 cho các trường riêng tư và 0219 cho các biến cục bộ, không phải 169 (đưa ra cảnh báo về việc không thể khôi phục cảnh báo thay thế).
Draco18s không còn tin tưởng SE

14

Một "giải pháp" khác để khắc phục những cảnh báo này là tạo cấu trúc public. Sau đó, các cảnh báo không được đưa ra vì trình biên dịch không thể biết liệu các trường có đang được sử dụng (gán) bên ngoài hợp ngữ hay không.

Điều đó nói rằng, các thành phần "interop" thường không được công khai, mà là internalhoặc private.


2
Nice, điều này ẩn cảnh báo ... nhưng thiết lập một ví dụ structnhư publiccó nhiều khả năng là một sai lầm hơn so với cảnh báo chúng tôi đang cố gắng để che giấu. (Bạn có thể không nên để lộ các loại được sử dụng cho triển khai nội bộ một cách không cần thiết và các loại có trường công khai có thể không thuộc API công khai). Chỉ để củng cố lời khuyên của bạn rằng các loại như vậy nên là “đúng hơn internalhoặc private” ;-).
binki

cảm ơn tuyệt vời - đây là những gì tôi cần. Tôi đang sử dụng JsonConvert.DeserializeObjectvà tôi đang deserializing thành một lớp công khai chỉ có tất cả các thuộc tính được hiển thị để tôi biết những gì sẽ được trả về. Chỉ cần làm cho nó trở thành một lớp công khai trống với tất cả các chuỗi công khai là mã ngắn đẹp và giờ không còn cảnh báo nữa. Có lẽ việc sử dụng một lớp động sẽ tốt hơn vì bạn không phải trình bày rõ ràng những gì trong mảng, nhưng tôi nghĩ đây sẽ là một tham chiếu tốt cho bất kỳ ai hy vọng sử dụng đối tượng.
user1274820

6

Tôi đã VS để tạo khung triển khai System.ComponentModel.INotifyPropertyChangedvà các sự kiện được triển khai dưới dạng các trường kích hoạt cảnh báo CS0067.

Để thay thế cho giải pháp được đưa ra trong câu trả lời được chấp nhận, tôi đã chuyển đổi các trường thành thuộc tính và cảnh báo biến mất .

Điều này có ý nghĩa vì đường cú pháp khai báo thuộc tính được biên dịch thành một trường cộng với các phương thức getter và / hoặc setter (thêm / bớt trong trường hợp của tôi) tham chiếu đến trường. Điều này đáp ứng trình biên dịch và các cảnh báo không được đưa ra:

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
}

Giải pháp của bạn phù hợp hơn nhiều so với việc tắt cảnh báo, nhưng nó có thể ảnh hưởng đến một số thuộc tính chỉ trường, ví dụ: MarshalAsAttribute.
HuBeZa

1
Thông tin: Các trường riêng tư thực tế được tạo trong trường hợp này có thể có tên "lạ", chẳng hạn như <GetHeader>k__BackingField, tùy thuộc vào chi tiết triển khai của trình biên dịch C # được sử dụng.
Jeppe Stig Nielsen

1

Người dùng C / C ++ phải (void)var;ngăn chặn các cảnh báo về biến không sử dụng. Tôi vừa phát hiện ra rằng bạn cũng có thể chặn cảnh báo biến không sử dụng trong C # bằng các toán tử bitwise:

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

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

Cả hai biểu thức đều không tạo ra cảnh báo biến không sử dụng trong trình biên dịch VS2010 C # 4.0 và Mono 2.10.


4
Hoạt động cho uint, nhưng không cho các loại khác, như Exception. Bạn có biết một thủ thuật chung tương đương với C / C ++ var;không?
manuell

1
@manuell xin chào từ tương lai! Bạn có thể sử dụng error.ToString();cho một biến loạiException
Sv443

Cảm ơn từ bây giờ. Thủ thuật đó có thêm mã thực trong thời gian chạy, phải không?
manuell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.