== が参照を比較してしまう理由
classの==は既定でオブジェクトの参照(同一性)を比較します。フィールドの値が同じでも、別々に生成したインスタンスはfalseになります。
なぜエラーが出ないのか
出力: False
(エラーなし)- C#は何も報告しません。文法として正しいためです
出力: False- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 class Point { public int X; public int Y; } 2 class Program { 3 static void Main(string[] args) { 4 Point a = new Point { X = 1, Y = 2 }; 5 Point b = new Point { X = 1, Y = 2 }; ^ 6 System.Console.WriteLine(a == b); 7 } 8 }
出力: False
クラスの==は既定では参照の比較です。フィールドの値が同じでも別のインスタンスならfalseになります。
直し方: new Point { X = 1, Y = 2 } を a にします。
広告
広告スロット(未設定)
パターン2
1 class Item { public string Name; } 2 class Program { 3 static void Main(string[] args) { 4 Item a = new Item { Name = "pen" }; 5 Item b = new Item { Name = "pen" }; ^ 6 System.Console.WriteLine(a == b); 7 } 8 }
出力: False
Nameの値が同じ"pen"でも、別々にnewしたインスタンスは別物として扱われます。
直し方: new Item { Name = "pen" } を a にします。
パターン3
1 class Coord { public double Lat; public double Lng; } 2 class Program { 3 static void Main(string[] args) { 4 Coord a = new Coord { Lat = 35.0, Lng = 139.0 }; 5 Coord b = new Coord { Lat = 35.0, Lng = 139.0 }; ^ 6 System.Console.WriteLine(a == b); 7 } 8 }
出力: False
値を比較したい場合はEqualsをオーバーライドするか、recordやstructの利用を検討します。
直し方: new Coord { Lat = 35.0, Lng = 139.0 } を a にします。
よくある誤解
値が同じなら==がtrueになると期待しがちですが、値の比較にしたい場合はEqualsのオーバーライドやrecord型の利用が必要です。
まとめ
== が参照を比較してしまう理由は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。
関連するエラー
- struct(値型)とclass(参照型)のコピーの違いstructは値型、classは参照型です。
- is inaccessible due to its protection level の原因と直し方privateなメンバーにクラスの外部からアクセスしようとすると出るコンパイルエラーです。