JetBrains Rider 2024.1 ヘルプ

コード検査: おそらく不純な struct メソッドが読み取り専用変数で呼び出されます: 呼び出し前に常にコピーされる構造体値

次のコードを考えてみましょう:

class Test { struct MyStruct { public int Value; public void IncrementValue() { Value +=1; } } readonly MyStruct _readonlyStruct = new MyStruct(); public void RunTest() { // Warning: Impure method is called for readonly field of value type _readonlyStruct.IncrementValue(); Console.WriteLine(_readonlyStruct.Value); // 0 } }

最終的に出力に 0 が含まれることになりますが、事前に IncrementValue() を呼び出すと 1 になるはずです。これは、値型の readonly フィールドにアクセスすると、呼び出し元がフィールドを変更できないように、そのコピーが作成されるために発生します。

上記の例の _readonlyStruct.IncrementValue() は、_readonlyStruct のコピーを作成し、その Value フィールドを 1 に変更してから、コピーを破棄します。

ただし、このような問題は、不純なメソッド、つまり上記の IncrementValue() のようにオブジェクトの状態を変更するメソッドでのみ発生します。同様の状況で純粋なメソッドを呼び出すことは問題ではありません。なぜなら、コピーで呼び出されるかどうかに関係なく、状態は変更されず、メソッドから期待どおりの結果が得られるからです。

偽陽性

残念ながら、JetBrains Rider はメソッドが純粋かどうかを常に判断できるとは限らず、そのためこのインスペクションは誤検知の警告を生成することがありますが、[Pure] で修飾されたメソッド (JetBrains.Annotations.PureAttributeSystem.Diagnostics.Contracts.PureAttribute の両方を使用できます) は常に純粋であるとみなされ、警告は生成されません。

.NET フレームワークおよびその他の頻繁に使用されるライブラリの多くのメソッドは、外部アノテーションを介して [Pure] でアノテーションが付けられていることに注意してください。

問題を修正する

JetBrains Rider はこのインスペクションのためのクイックフィックスを提供していません。

フィールドの状態を変更することがコード内で意図されている場合は、readonly 修飾子を削除することによってフィールドを変更可能にすることができます。

フィールドを不変にしたい場合は、フィールドに対して不純なメソッドが呼び出されないようにコードを書き直す必要があります。

呼び出されたメソッドが純粋で、警告が誤検知である場合は、[Pure]アノテーションを付けるかこのインスペクションを抑制することができます。