web-dev-qa-db-ja.com

ReSharper Curiosity:「パラメータは前提条件チェックにのみ使用されます。」

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

2番目のメソッドValidateCorrespondingValueTypeの「settingValue」パラメーターは、R​​eSharperによって次のメッセージでグレー表示されます。「パラメーター 'settingValue'は前提条件チェックにのみ使用されます」。

88
Corpsekicker

それは判断ではなく、助けようとしている:)

パラメーターが例外をスローするためのチェックとしてのみ使用されることをReSharperが確認した場合、グレー表示され、「実際の」作業に実際に使用していないことを示します。これはおそらく間違いです-使用しないパラメーターを渡すのはなぜですか?通常、前提条件で使用したが、コードの他の場所で使用することを忘れた(または必要なくなった)ことを示します。

メソッドはアサーションメソッドなので(つまり、有効であるとアサートするだけです)、ReSharperの アノテーション属性 を使用して、ValidateCorrespondingValueTypeをアサーションメソッドとしてマークすることにより、メッセージを抑制することができます。 、特に[AssertionMethod]属性:

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

興味深いことに、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));
    }
}
15
Holf

この問題に対する私の好ましい解決策は、resharperにパラメーターisが使用されていると考えさせることです。これには、UsedImplicitlyなどの属性を使用するよりも利点があります。これは、doそのパラメーターの使用を停止すると、resharperが再び警告を開始するためです。属性を使用する場合、resharperは将来の実際の警告もキャッチしません。

再シャーパーにパラメーターが使用されていると思わせる簡単な方法は、throwをメソッドに置き換えることです。代わりに...

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

...あなたが書く:

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

これは将来のプログラマーのためにうまく自己文書化され、再シャーパーは泣き言をやめます。

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

例外の拡張メソッドis名前空間汚染ですが、かなり含まれています。

5
Eamon Nerbonne

以下は(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によって行われた)が異なる結果を与えることは興味深いです。パターンマッチングは、単に2番目のバージョンを選択しないようです。

5
Maryn