ReSharper好奇心:“参数仅用于前提条件检查”。

为什么ReSharper判断我这个代码?

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

第二种方法ValidateCorrespondingValueType的“settingValue”参数用ReSharper用以下消息变灰:“Parameter'settingValue'只用于前提条件检查。

这不是判断,它试图帮助:)

如果ReSharper发现一个参数只是作为一个检查来抛出一个exception,它会灰色的,表明你没有真正的使用它来做“真正的”工作。 这很可能是一个错误 – 为什么传入一个你不会使用的参数呢? 它通常表示您已经在前提条件下使用了它,但是随后被遗忘(或不再需要)在代码的其他地方使用它。

由于这个方法是一个断言方法(也就是说,它所做的只是断言它是有效的),所以可以通过使用ReSharper的注解属性 ,特别是[AssertionMethod]属性,将ValidateCorrespondingValueType标记为一个断言方法来抑制消息:

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

有趣的是,如果您在C#6中使用新的function名称,ReSharper nameof

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

以下解决了这个问题(在ReSharper 2016.1.1,VS2015中),但我不确定它是否解决了“正确”的问题。 无论如何,它显示了ReSharper关于这个话题的机制的含糊性:

这产生了警告:

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

但是这不是:

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

有趣的是,等效代码(ReSharper完成的反转:D)给出了不同的结果。 看起来,模式匹配根本没有拿起第二个版本。

我对这个问题的首选解决方法是让resharper认为参数使用。 与使用UsedImplicitly属性相比,这具有优势,因为如果您停止使用该参数,resharper将再次启动警告。 如果您使用属性,resharper也不会捕获未来的真实警告。

一个简单的方法让resharper认为参数被使用是用一个方法replacethrow 。 所以,而不是…

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

…你写:

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

这对于未来的程序员来说是很好的自我logging,并且resharper停止抱怨。

ThrowPreconditionViolation的实现是微不足道的:

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

Exception的扩展方法命名空间污染,但它是相当包含的。

Interesting Posts