【C#入門】Equalsメソッドの挙動を徹底解説!参照比較と値比較の違い、オーバーライドによる実装方法
C#におけるEqualsメソッドは、オブジェクト同士を比較するための基本的な手段です。しかし、デフォルトの動作では「参照の一致」を判定するため、プロパティの値が完全に同じでも、別々のインスタンスであればfalseが返されます。
本記事では、この挙動を具体的なサンプルコードとともに解説し、EqualsメソッドとGetHashCodeメソッドをオーバーライドすることで「値の等価性」を実現する方法を紹介します。
デフォルトのEqualsメソッドの挙動
まず、Employeeクラスのインスタンスeを作成し、それを変数e2に代入するケースを見てみましょう。この場合、両方の変数は同一のオブジェクト(同じ参照)を指しているため、Equalsは期待どおりtrueを返します。
一方、2つ目のケースでは、プロパティの値はまったく同じでも、それぞれ独立した新しいインスタンスを作成しています。この場合、Equalsはプロパティの値をチェックせず、常にfalseを返します。これは、引数が異なるオブジェクトを参照しているためです。
例1:オーバーライドしない場合
class Program{
static void Main(string[] args){
Employee e = new Employee();
e.Name = "Test";
e.Age = 27;
Employee e2 = new Employee();
e2 = e;
var valueEqual = e.Equals(e2);
Console.WriteLine(valueEqual);
// 2つ目のケース:値は同じだが別インスタンス
Employee e1 = new Employee();
e1.Name = "Test";
e1.Age = 27;
var valueEqual1 = e.Equals(e1);
Console.WriteLine(valueEqual1);
Console.ReadLine();
}
}
class Employee{
public int Age { get; set; }
public string Name { get; set; }
}
出力結果
True False
最初の比較では同じ参照を指しているためTrue、2つ目の比較では別インスタンスのため値が同じでもFalseになっていることが確認できます。
Equalsメソッドをオーバーライドして値を比較する
プロパティの値に基づいて等価性を判定したい場合は、Equalsメソッドをオーバーライドします。その際、C#の規約上、GetHashCodeメソッドも必ず一緒にオーバーライドすることが推奨されています。これは、DictionaryやHashSetなどのハッシュベースのコレクションでオブジェクトを正しく扱うために必要だからです。
例2:EqualsとGetHashCodeをオーバーライドした場合
class Program{
static void Main(string[] args){
Employee e = new Employee();
e.Name = "Test";
e.Age = 27;
Employee e2 = new Employee();
e2 = e;
var valueEqual = e.Equals(e2);
Console.WriteLine(valueEqual);
Employee e1 = new Employee();
e1.Name = "Test";
e1.Age = 27;
var valueEqual1 = e.Equals(e1);
Console.WriteLine(valueEqual1);
Console.ReadLine();
}
}
class Employee{
public int Age { get; set; }
public string Name { get; set; }
public override bool Equals(object? obj){
if (obj == null)
return false;
if (this.GetType() != obj.GetType())
return false;
Employee p = (Employee)obj;
return (this.Age == p.Age) && (this.Name == p.Name);
}
public override int GetHashCode(){
return Age.GetHashCode() ^ Name.GetHashCode();
}
}
出力結果
True True
Equalsをオーバーライドすることで、たとえ別々のインスタンスでも、プロパティの値が一致していればtrueが返されるようになりました。
まとめ
- デフォルトの
Equalsメソッドは参照の一致を判定するため、別インスタンス同士の比較では値が同じでもfalseになる。 - 値ベースの比較を行いたい場合は、
EqualsメソッドとGetHashCodeメソッドの両方をオーバーライドする。 GetHashCodeのオーバーライドを省略すると、DictionaryやHashSetなどで意図しない動作が発生する可能性があるので注意が必要。
なお、C# 9以降ではrecord型を使用することで、このような値の等価性の実装を自動的に生成できます。ボイラープレートコードを書きたくない場合は、record型の活用も検討してみてください。
-
WindowsサンドボックスとVMware・VirtualBoxを併用する方法|ブートエントリの切り替え手順
Windows サンドボックスは、Windows 11/10 上で動作するために Hyper-V 機能を利用しています。そのため、Hyper-V が有効になっている環境では、VMware や VirtualBox といったサードパーティ製の仮想化ソフトウェアを同時に実行することができません。 しかし、この制限はいくつかの工夫によって回避できます。Windows Sandbox の利用を目的として Windows 10(または Windows 11)へアップグレードしたものの、特定の作業では引き続き PC 上の仮想マシンに頼っている方にとって、この方法は非常に役立つでしょう。 Windows
-
CortanaとAlexaを連携して使う方法|Windows 10とAmazon Echoで両アシスタントを活用
Microsoftは、Build開発者向けカンファレンスでの発表をもとに、Windows 10 PCへのAlexa搭載と、Amazon EchoスピーカーへのCortana搭載を実現しました。現在、プレビュー版は米国限定で提供されていますが、この2大音声アシスタントの提携は今後さらに発展していくことが期待されます。 私たちが暮らす現代は多様化した世界であり、1台のデバイスに複数のアシスタントを搭載することには大きなメリットがあります。個別のOSとしてではなく、まるでアプリのようにアシスタントへアクセスできるのは非常に便利です。 現時点での連携機能はまだ基本的なものですが、近いうちにCortan