ReSharper 2025.3 ヘルプ

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

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

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

ReSharper はこれらの警告を認識しており、それらに対して設計時の通知を提供しますが、さらに一歩進んで、意図しない参照比較の可能性がある別のケース (比較される型の 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 ReSharper issues its own warning here } }

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

ReSharper は、等価演算子や 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 }

このインスペクションはソリューション全体(参照ライブラリを含む)でインターフェースの実装を探しますが、その場所は必ずしも明らかではありません。以下の例では、ReSharper は 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() などの特定のメソッドを使用できます。

2024 年 2 月 11 日

関連ページ:

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

設計時コードインスペクションを構成する:デフォルトでは、ReSharper は、サポートされている言語に対応するすべてのファイルで設計時コードインスペクションを有効にします。必要に応じて、無効にすることができます。設計時コードインスペクションが有効かどうかに関係なく、コードインスペクションは常に特定のスコープで実行できます。メインメニューからを選択するか、Alt+R O を押してから、左側のを選択します。設計時コードインスペクションを切り替えるには、コード分析を有効にするチェックボックスを使用し...

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

ReSharper は、エディターでコードファイルを開くとすぐに分析を開始し、最後まで編集を続けます。検出されたすべてのコードの問題は、重大度に従ってエディターでハイライトされます。問題のマップは、エディターウィンドウの右側のマーカーバーにも表示されます。ここでは、ファイルのステータスを即座に確認し、マークをクリックして特定のコードの問題に移動できます。デザインタイムインスペクションの機能:ReSharper によって実行されるデザインタイムコードインスペクションを説明するために、エディターに...

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

次のコードスニペットを考えてみましょう。IEnumerable<string> names = GetNames(); foreach (var name in names) Console.WriteLine(