ReSharper Curicious: “参数仅用于前置条件检查。”

为什么 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 的“ setingValue”参数由 ReSharper 用以下消息变成灰色: “参数‘ setingValue’仅用于前置条件检查。”

22583 次浏览

这不是评判,这是试图帮助:)

如果 ReSharper 看到一个参数只被用作检查来抛出异常,它会将其变成灰色,表明您实际上并没有将其用于“实际”工作。这很可能是一个错误——为什么要传递一个不打算使用的参数呢?它通常表示您已经在前置条件中使用了它,但是随后忘记(或不再需要)在代码的其他地方使用它。

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

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

有趣的是,如果使用 C # 6中新的 nameof功能,ReSharper 会退出:

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


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

我对这个问题的首选解决方案是使再锐化器认为参数 使用。这比使用 UsedImplicitly这样的属性有一个优势,因为如果 停止使用该参数,resharper 将再次开始警告您。如果使用属性,resharper 也不会捕捉到未来的真实警告。

一个简单的方法,使再锐化器认为参数是用来取代 throw的方法。所以不是..。

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

...you write:

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

这对于未来的程序员来说是很好的自我记录,并且 resharper 不再抱怨。

ThrowPre條的实现是微不足道的:

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

An extension method on Exception namespace pollution, but it's fairly contained.

下面修复了这个问题(在 ReSharper2016.1.1,VS2015中) ,但我不确定它是否解决了“正确”的问题。无论如何,它显示了 ReSharper 在这个话题上的模棱两可:

This yields the warning:

    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 disable once ParameterOnlyUsedForPreconditionCheck.Local

在类声明的上面添加这个以关闭整个文件:

     // ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local

我相信下面是一个合法的情况下,我检查所有项目列表与 lambda Any方法。 然后我使用相同的方式下一行,但重新锐化失败。

if (actions.Any(t => t.Id == null)) // here says Paramter t is used only for precondition check(s)
throw new Exception();
actionIds = actions.Select(t => t.Id ?? 0).ToList();

我不得不无视他的评论。

使用以上参数的注释

//ReSharper 禁用 once Parameter terOnlyUseForPreconttionCheck. Local

禁用莱德的暗示