2014-11-19 12 views
59

Tại sao ReSharper lại đánh giá tôi cho mã này?Sự tò mò của ReSharper: "Tham số chỉ được sử dụng cho kiểm tra điều kiện tiên quyết."

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); 
     } 
    } 

Phương pháp thứ hai "settingValue" tham số ValidateCorrespondingValueType được chuyển sang màu xám với thông báo sau bởi ReSharper: " 'settingValue' Parameter chỉ được sử dụng để kiểm tra điều kiện tiên quyết (s)."

+0

Bạn có thể di chuyển khai báo và gán 'exceptionMessage' vào' if'-block :) – AakashM

Trả lời

64

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 tấm séc để ném một ngoại lệ, nó Grays nó ra, chỉ ra rằng bạn không thực sự sử dụng nó cho "thực sự" làm việc. Điều này rất có thể là một sai lầm - tại sao vượt qua trong một tham số bạn sẽ không sử dụng? Nó thường chỉ ra rằng bạn đã sử dụng nó trong một điều kiện trước, nhưng sau đó bị lãng quên (hoặc không còn cần) để sử dụng nó ở nơi khác trong mã.

Kể từ khi phương pháp này là một phương pháp khẳng định (có nghĩa là, tất cả nó làm là khẳng định đó là hợp lệ), bạn có thể ngăn chặn được thông báo bằng cách đánh dấu các ValidateCorrespondingValueType như một phương pháp khẳng định, sử dụng, đặc biệt là [AssertionMethod] thuộc tính ReSharper annotation attributes:

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

Đó là một kiểm tra tốt đẹp, nhưng trong trường hợp * này * R đã vượt quá một chút, bạn sẽ không nói? Việc kiểm tra kiểu 'settingValue' không thể là một điều kiện ** trước **, vì điều nó đang được kiểm tra chống lại không được biết đến cho đến khi một số công việc đã được thực hiện bên trong phần thân của phương thức! – AakashM

+6

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

+0

Ohhhh Tôi hiểu rồi. – AakashM

6

Điều thú vị là, ReSharper lùi lại nếu bạn sử dụng nameof chứ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)); 
    } 
} 
4

giải pháp ưa thích của tôi cho vấn đề này là làm cho resharper mỏng k tham số là sử dụng. Điều này có lợi thế hơn khi sử dụng thuộc tính như UsedImplicitly vì nếu bạn từng làm ngừng sử dụng thông số đó, tính năng chia sẻ lại sẽ bắt đầu cảnh báo lại cho bạn. Nếu bạn sử dụng thuộc tính, tính năng chia sẻ lại sẽ không bắt được cảnh báo thực trong tương lai.

Cách dễ dàng để thực hiện việc chia sẻ lại nghĩ rằng paramter được sử dụng là thay thế throw bằng phương pháp. Vì vậy, thay vì ...

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

... bạn viết:

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

này là độc đáo tự ghi lại cho các lập trình viên trong tương lai, và resharper bỏ rên rỉ.

Việc thực hiện ThrowPreconditionViolation là tầm thường:

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 pháp mở rộng trên Exception namespace ô nhiễm, nhưng nó khá kín.

+0

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

5

Sau đây khắc phục vấn đề (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ự nhập nhằng trong cơ ReSharper liên quan đến chủ đề này:

Điều này mang lại 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 (sự đảo ngược được thực hiện bởi ReSharper: D) cho kết quả khác nhau. Dường như việc khớp mẫu đơn giản không nhận phiên bản thứ hai.

Các vấn đề liên quan