C# 再敏锐的好奇心:“我的好奇心”;参数仅用于先决条件检查。”;

C# 再敏锐的好奇心:“我的好奇心”;参数仅用于先决条件检查。”;,c#,resharper,preconditions,C#,Resharper,Preconditions,为什么ReSharper会因为这个代码而评判我 private Control GetCorrespondingInputControl(SupportedType supportedType, object settingValue) { this.ValidateCorrespondingValueType(supportedType, settingValue); switch(supportedType) {

为什么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显示为灰色,并显示以下消息:
“参数'settingValue'仅用于先决条件检查。”

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

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

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

[断言方法]
private void ValidateCorrespondingValueType(SupportedType SupportedType,object settingValue)
{
// …
}

有趣的是,如果您在C#6:


我对此问题的首选解决方案是让resharper认为使用了该参数。与使用
usedimplicity
等属性相比,这有一个优势,因为如果您停止使用该参数,resharper将再次开始警告您。如果使用属性,resharper也不会捕获将来的真正警告

让resharper认为使用了参数的一个简单方法是用方法替换
throw
。所以不是

if(myPreconditionParam == wrong)
    throw new Exception(...);
……你写道:

if(myPreconditionParam == wrong)
    new Exception(...).ThrowPreconditionViolation();
对于未来的程序员来说,这是一个很好的自我记录,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;
    }
}

异常的一个扩展方法是名称空间污染,但它的内容相当丰富。

以下内容解决了这个问题(在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 disable once ParameterOnlyUsedForPreconditionCheck.Local
将此项添加到类声明上方,以关闭整个文件的类声明:

     // ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local

我相信下面是一个合法的例子,我用lambda
Any
方法检查列表中的所有项目。 然后我用同样的方法处理下一行,但是resharper失败了

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

我不得不用注释忽略。

您可以将
exceptionMessage
的声明和赋值移动到
if
-block:)中,您也可以使用以下方法执行此操作:expectedText+=“”;它停止抱怨,因为你在方法中使用了它。这是一个很好的检查,但在这种情况下,R#已经超过了一点,你说呢?检查
settingValue
的类型不可能是一个先决条件,因为在方法主体内完成某些工作之前,它所检查的对象是未知的!这就是为什么需要告诉ReSharper这是一个断言方法。此方法的唯一要点是对另一种方法执行前置条件检查。这是一个断言,但ReSharper无法知道这一点,除非你用
[AssertionMethod]
告诉它。我最后只是将检查严重性更改为“不显示”,这是另一个选项。如果可以独立于常规未使用参数检查禁用“仅前置条件”检查,这可能是一个有用的功能;目前,检查混淆了两个不同严重性的问题,通常在某些情况下使此功能无效。我也非常怀疑仅仅为了让源代码分析工具满意而在代码中添加注释或属性的想法,因此目前我认为没有一个令人满意的解决方案。它可能试图提供帮助,但太激进了。现在,如果您验证该值,然后再也不使用它,很好,这可能是一个错误。然而,当我只使用错误中的值时,它却在向我咆哮。还有什么能不是故意的呢?+1提到
[usedimplicity]
,我不想使用
[AssertionMethod]
,因为它不是,在我的例子中,它的使用听起来更准确(我是在向构造函数中的回调传递一个值并返回构造的对象)。这个答案适合我,与添加nuget Package相比,它的侵入性更小。缺点是您不能指定您所指的witch参数。@comecme您可以通过在特定参数周围使用注释来禁用单个参数。在这种情况下,我建议将每个参数放在自己的行上;仍然难看,但(在我看来)不那么难看。
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();