JetBrains Rider 2024.1 ヘルプ

コード検査: 考えられる意図しない参照の比較

C# コンパイラーは、相互に継承する型のオブジェクトに対して等価演算子(== または !=)を使用し、これらの演算子をオーバーライドする型のうちの 1 つのみの型の場合に、「意図しない参照の比較」警告(CS0252/CS0253)を発行します。

いずれかの型で等価演算子がオーバーライドされるということは、この型のオブジェクトが比較されるときに値が等しいことが期待されることを意味します。これらのオブジェクトを等価演算子がオーバーライドされていない型のオブジェクトと比較すると、参照の等価性をチェックする System.Object のオーバーロードが使用されることになります。この状況ではオブジェクト参照の比較が誤っている可能性が高いため、警告が発行されます。

JetBrains Rider はこれらの警告を認識しており、それらに対して設計時の通知を提供しますが、さらに一歩進んで、意図しない参照比較の可能性がある別のケース (比較される型の 1 つだけが Equals() をオーバーライドする場合) を検出します。2 番目のオブジェクトの型に対して Equals() がオーバーライドされていない場合、比較は System.ObjectEquals() の実装にフォールバックされ、参照同一性チェックが実行されますが、これは値型には望ましくない可能性があります。

両方の状況を示すコード一覧を示します。

class MyType { } class TypeWithEquals : MyType { public override bool Equals(object obj) { throw new NotImplementedException(); } } class TypeWithEqOperators : MyType { public static bool operator ==(TypeWithEqOperators left, TypeWithEqOperators right) { throw new NotImplementedException(); } public static bool operator !=(TypeWithEqOperators left, TypeWithEqOperators right) { throw new NotImplementedException(); } } class Test { public Test(TypeWithEquals withEquals, TypeWithEqOperators withEqOperators, MyType parentObject) { bool a = withEqOperators == parentObject; // CS0253 bool b = withEquals == parentObject; // No compiler warnings, but JetBrains Rider issues its own warning here } }

このインスペクションのもう 1 つのケースは、等価演算子(== または !=)を使用してインターフェースタイプを比較することです。これらの演算子は静的であるため、インターフェースの実装で等価演算子が値の比較にオーバーライドされた場合でも、コンパイラーはデフォルトで System.Object.ReferenceEquals() (つまり、参照比較)になります。

JetBrains Rider は、等価演算子や Equals() をオーバーライドするインターフェース実装を探し、そのような実装を検出すると、警告を発行します。

interface ISomeInterface{ } class SomeImplementation : ISomeInterface { public override bool Equals(object obj) => throw new NotImplementedException(); public override int GetHashCode() => throw new NotImplementedException(); } void ATest(ISomeInterface x, ISomeInterface y) { bool a = x == y; //Possible unintended reference comparison }

このインスペクションはソリューション全体(参照ライブラリを含む)でインターフェースの実装を探しますが、その場所は必ずしも明らかではありません。以下の例では、JetBrains Rider は mscorlib 内の Equals() をオーバーライドする ICollection<object> の実装を検出し、ICollection<object> の独自の実装が Equals() または等価演算子をオーバーライドしない場合でも警告を発行します。

void SomeTest(ICollection<object> x, ICollection<object> y) { bool a = x == y; //Possible unintended reference comparison }

このケースは少し慎重に思えるかもしれませんが、インターフェースを比較するために非静的メソッドを使用すると、コードがより簡単になり、おそらくより安全になる可能性があります。つまり、参照等価をチェックする場合は ReferenceEquals()、実装ではそれがオーバーライドされると予想される場合は Equals()、コレクションには同じ順序で同じオブジェクトが含まれるかどうかをチェックする Enumerable.SequenceEqual() などの特定のメソッドを使用できます。

関連ページ:

コードインスペクション設定を構成する

設計時コードインスペクションを構成する:デフォルトでは、JetBrains Rider はサポートされている言語に対応するすべてのファイルで設計時コードインスペクションを有効にします。必要に応じて、無効にすることができます。設計時コードインスペクションが有効かどうかにかかわらず、コードインスペクションを特定の範囲でいつでも実行できます。「鉛筆」ウィジェットを使用して、エディターから直接インスペクション設定をすばやく調整するか、設定でより詳細な構成を行うことができます。を押すか、メニューから(W...

設計時にコードの問題を分析する

JetBrains Rider は、エディターでコードファイルを開くとすぐに、コードファイルが閉じられるまで分析を開始します。検出されたすべてのコードの問題は、重大度に応じてエディターでハイライトされます。問題のマップは、エディターウィンドウの右側のエラーストライプにも表示されます。ここでは、ファイルのステータスを即座に確認し、マークをクリックして特定のコードの問題に移動できます。デザインタイムインスペクションの機能:デザイン時のインスペクション機能は、Rider エディターの基本機能への主要...

コード検査: 複数列挙の可能性

次のコードスニペットを考えてみましょう。IEnumerable<string> names = GetNames(); foreach (var name in names) Console.WriteLine("Found " + name); var allNames = new StringBuilder(); foreach (var name in names) allNames.Append(name + " "); がを返すと仮定すると、2 つのステートメントでこのコレク...