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


102

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"パラメータは、ReSharperによって次のメッセージでグレー表示されます。


あなたはの宣言と代入を移動することができますexceptionMessageif:) -ブロック
AakashM

メソッドでこれを行うこともできます。expectedText+ = ""; メソッドで使用したため、文句を言うのをやめます。
PHPGuru 2018年

回答:


104

それは判断ではありません、それは助けようとしています:)

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

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

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

3
これはいいチェックですが、この場合はR#が少し行き過ぎですよね。メソッドの本体内で何らかの処理が行われるまで、チェック対象の内容がわからないため、settingValueの型のチェックは前提条件にすることはできません。
AakashM 2014年

6
そのため、ReSharperにアサーションメソッドであることを伝える必要があります。このメソッドの唯一のポイントは、別のメソッドの事前条件チェックを実行することです。これはアサートですが、ReSharperは、で指示しない限りそれを知ることができません[AssertionMethod]
citizenmatt 2014年

10
検査の重大度を「表示しない」に変更しただけですが、これは別のオプションです。
reggaeguitar 2014

61
通常の未使用のパラメーター検査とは別に「事前条件のみ」の検査を無効にできる場合、これは有用な機能だったかもしれません。現状では、検査により重大度の異なる2つの問題が混同され、特定の状況ではこの機能が役に立たなくなります。また、ソースコード分析ツールを満足させるために、コメントや属性をコードに追加するという考えにも非常に懐疑的です。そのため、現時点では問題に対する十分な解決策はないと思います。
Serge Belov、2015

7
それは助けようとしているかもしれませんが、あまりにも攻撃的です。さて、値を確認した後でそれを使用しない場合は、問題ありません。しかし、それは私がエラーの値のみを使用しているものを私に打ちのめしています。他にどのようにそれが意図的ではないことができますか?
Loren Pechtel、2015年

20

興味深いことに、nameofC#6の新機能を使用すると、ReSharperが後退します。

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

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

3
この回答は私に適しています。nugetパッケージを追加するよりも煩わしくない
DanielV 2018

8

以下は(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番目のバージョンを取得しないようです。


6

この問題に対する私の好ましい解決策は、パラメータ使用されていると再シャープ化させることです。これは、次のような属性を使用して以上の利点を持っているUsedImplicitlyあなたがいる場合ので 停止、そのパラメータを使用して、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;
    }
}

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


言及+1 [UsedImplicitly]、私は[AssertionMethod]それがそうでなかったので使用したくなかったし、使用した場合は暗黙的により正確に聞こえました(コンストラクタでコールバックに値を渡し、構築されたオブジェクトを返していました)。
MrLore 2017

1

他の人はすでに質問に回答していますが、警告をオフにする次の方法については誰も言及していません。

これをメソッドシグネチャの上に追加して、そのメソッドに対してのみオフにします。

    // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local

これをクラス宣言の上に追加して、ファイル全体に対してオフにします。

     // ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local

欠点は、あなたが意味する魔女パラメータを指定できないことです。
comecme

1
@comecme無効にして単一のパラメーターを無効にして、 その特定のパラメーターに関するコメントを復元できます。その場合は、すべてのパラメーターを1行に置くことをお勧めします。まだ醜いですが、それほどではありません(私の意見では)。
Travis
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.