ReSharper Curiosity: “Thông số chỉ được sử dụng cho (các) kiểm tra điều kiện trước.”


102

Tại sao ReSharper lại đánh giá tôi về mã này?

    private Control GetCorrespondingInputControl(SupportedType supportedType, object settingValue)
    {
        this.ValidateCorrespondingValueType(supportedType, settingValue);

        switch(supportedType)
        {
            case SupportedType.String:
                return new TextBox { Text = (string)settingValue };
            case SupportedType.DateTime:
                return new MonthPicker { Value = (DateTime)settingValue, ShowUpDown = true };
            default:
                throw new ArgumentOutOfRangeException(string.Format("The supported type value, {0} has no corresponding user control defined.", supportedType));
        }
    }

    private void ValidateCorrespondingValueType(SupportedType supportedType, object settingValue)
    {
        Type type;

        switch(supportedType)
        {
            case SupportedType.String:
                type = typeof(string);
                break;
            case SupportedType.DateTime:
                type = typeof(DateTime);
                break;
            default:
                throw new ArgumentOutOfRangeException(string.Format("The supported type value, {0} has no corresponding Type defined.", supportedType));
        }
        string exceptionMessage = string.Format("The specified setting value is not assignable to the supported type, [{0}].", supportedType);
        if(settingValue.GetType() != type)
        {
            throw new InvalidOperationException(exceptionMessage);
        }
    }

Tham số "settingValue" của phương thức thứ hai ValidateCorresp Tương ứngValueType chuyển sang màu xám với thông báo sau của ReSharper: "Tham số 'settingValue' chỉ được sử dụng cho (các) kiểm tra điều kiện trước."


Bạn có thể di chuyển tờ khai và phân công exceptionMessagevào if-block :)
AakashM

Bạn cũng có thể làm điều này trong phương thức: evalText + = ""; và nó ngừng phàn nàn kể từ khi bạn sử dụng nó trong phương pháp.
PHPGuru

Câu trả lời:


104

Nó không phán xét, nó đang cố gắng giúp đỡ :)

Nếu ReSharper thấy rằng một tham số chỉ được sử dụng như một phép kiểm tra để đưa ra một ngoại lệ, nó sẽ chuyển sang màu xám, cho thấy rằng bạn không thực sự sử dụng nó cho công việc "thực sự". Đây rất có thể là một sự nhầm lẫn - tại sao lại chuyển vào một tham số mà bạn không sử dụng? Nó thường chỉ ra rằng bạn đã sử dụng nó ở điều kiện trước, nhưng sau đó quên (hoặc không cần nữa) để sử dụng nó ở nơi khác trong mã.

Vì phương thức là một phương thức xác nhận (nghĩa là tất cả những gì nó làm là khẳng định nó hợp lệ), bạn có thể chặn thông báo bằng cách đánh dấu ValidateCorrespondingValueTypelà phương thức xác nhận, sử dụng các thuộc tính chú thích của ReSharper , cụ thể là [AssertionMethod]thuộc tính:

[AssertionMethod]
private void ValidateCorrespondingValueType(SupportedType supportedType, object settingValue)
{
  // …
}

3
Đó là một tấm séc tốt đẹp, nhưng trong này trường hợp R # đã qua đạt một chút, bạn sẽ không nói? Vui lòng cung trên settingValue's loại có thể không thể trở thành một tiền -condition, vì điều đó đang được kiểm tra đối không được biết cho đến khi một số công việc đã được thực hiện trong cơ thể của phương pháp này!
AakashM

6
Đó là lý do tại sao bạn cần nói với ReSharper rằng đó là một phương pháp xác nhận. Điểm duy nhất của phương pháp này là thực hiện kiểm tra điều kiện trước cho một phương pháp khác. Đó là một khẳng định, nhưng ReSharper không thể biết điều đó trừ khi bạn nói với nó [AssertionMethod].
citizenmatt

10
Tôi đã kết thúc chỉ thay đổi Mức độ nghiêm trọng của kiểm tra thành "Không hiển thị", đây là một tùy chọn khác.
reggaeguitar

61
Nó có thể là một tính năng hữu ích, nếu người ta có thể vô hiệu hóa kiểm tra 'chỉ tình trạng trước' một cách độc lập với kiểm tra thông số không sử dụng thường xuyên; vì nó có nghĩa là việc kiểm tra kết hợp hai vấn đề có mức độ nghiêm trọng khác nhau và thường làm cho chức năng này trở nên vô dụng trong một số tình huống nhất định. Tôi cũng rất nghi ngờ ý tưởng thêm nhận xét hoặc thuộc tính vào mã chỉ để giữ cho công cụ phân tích mã nguồn hoạt động tốt, vì vậy hiện tại tôi không nghĩ có giải pháp thỏa đáng cho vấn đề này.
Serge Belov

7
Nó có thể đang cố gắng giúp đỡ nhưng nó quá hung hăng. Bây giờ, nếu bạn xác minh giá trị và sau đó không bao giờ sử dụng nó, tốt thôi, đó có thể là một lỗi. Tuy nhiên, nó đang ngấu nghiến tôi về một thứ mà tôi chỉ sử dụng giá trị trong lỗi. Làm thế nào khác có thể là bất cứ điều gì khác ngoài chủ ý?
Loren Pechtel

20

Thật thú vị, ReSharper sẽ hỗ trợ nếu bạn sử dụng nameofchức năng mới trong C # 6:

static void CheckForNullParameters(IExecutor executor, ILogger logger)
{
    if (executor == null)
    {
        throw new ArgumentNullException(nameof(executor));
    }

    if (logger == null)
    {
        throw new ArgumentNullException(nameof(logger));
    }
}

3
câu trả lời này phù hợp với tôi, nó là ít xâm nhập hơn thêm một gói NuGet
DanielV

8

Cách sau khắc phục sự cố (trong ReSharper 2016.1.1, VS2015), nhưng tôi không chắc nó giải quyết được vấn đề 'đúng'. Trong mọi trường hợp, nó cho thấy sự mơ hồ trong cơ chế của ReSharper liên quan đến chủ đề này:

Điều này dẫn đến cảnh báo:

    private void CheckForNull(object obj)
    {
        if (ReferenceEquals(obj, null))
        {
            throw new Exception();
        }
    }

Nhưng điều này không:

    private void CheckForNull(object obj)
    {
        if (!ReferenceEquals(obj, null))
        {
            return;
        }
        throw new Exception();
    }

Điều thú vị là mã tương đương (đảo ngược được thực hiện bởi ReSharper: D) cho kết quả khác nhau. Có vẻ như việc khớp mẫu đơn giản không chọn phiên bản thứ hai.


6

Giải pháp ưa thích của tôi cho vấn đề này là làm cho người bán lại nghĩ rằng tham số được sử dụng. Điều này có lợi thế hơn sử dụng một thuộc tính như UsedImplicitlybởi vì nếu bạn đã bao giờ làm dừng sử dụng tham số đó, resharper sẽ bắt đầu cảnh báo bạn một lần nữa. Nếu bạn sử dụng một thuộc tính, trình sạc lại cũng sẽ không nhận được các cảnh báo thực trong tương lai.

Một cách dễ dàng để khiến resharper nghĩ rằng paramter được sử dụng là thay thế throwbằng một method. Vì vậy, thay vì ...

if(myPreconditionParam == wrong)
    throw new Exception(...);

...bạn viết:

if(myPreconditionParam == wrong)
    new Exception(...).ThrowPreconditionViolation();

Điều này là độc đáo để tự ghi lại tài liệu cho các lập trình viên trong tương lai, và resharper sẽ thoát khỏi việc than vãn.

Việc thực hiện ThrowPreconditionViolation là không đáng kể:

public static class WorkAroundResharperBugs 
{
    //NOT [Pure] so resharper shuts up; the aim of this method is to make resharper 
    //shut up about "Parameter 'Foobaar' is used only for precondition checks" 
    //optionally: [DebuggerHidden]
    public static void ThrowPreconditionViolation(this Exception e)
    {
        throw e;
    }
}

Một phương thức mở rộng trên Exception ô nhiễm không gian tên, nhưng nó khá kín.


+1 để đề cập đến [UsedImplicitly], tôi không muốn sử dụng [AssertionMethod]vì nó không phải và sử dụng ngầm nghe có vẻ chính xác hơn trong trường hợp của tôi (tôi đang chuyển một giá trị cho một lệnh gọi lại trong một hàm tạo và trả về đối tượng đã xây dựng).
MrLore

1

Những người khác đã trả lời câu hỏi, nhưng không ai đề cập đến các cách tắt cảnh báo sau đây.

Thêm điều này bên trên chữ ký phương thức để tắt nó chỉ cho phương thức đó:

    // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local

Thêm điều này vào phía trên khai báo lớp để tắt nó cho toàn bộ tệp:

     // ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local

Một bất lợi là bạn không thể chỉ định tham số phù thủy mà bạn muốn.
comecme

1
@comecme Bạn có thể tắt cho một tham số bằng cách sử dụng tắt và khôi phục các nhận xét xung quanh tham số cụ thể đó. Tôi khuyên bạn nên đặt mọi tham số trên dòng riêng của nó trong trường hợp đó; vẫn xấu nhưng ít như vậy (theo tôi).
Travis
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.