本文へスキップ
BecomeCoder

C#オブジェクト指向コース · 第1章 オブジェクト指向 · レッスン11

object基底クラスと sealed / partial

ブラウザで完結

導入

C#のすべての型は、共通の親object継承しています。だからToString()Equals()GetHashCode()はどんなオブジェクトにもあります。これらを正しくオーバーライドすると、「意味的に等しいか」を自分で定義でき、DictionaryHashSetのキーとしても正しく振る舞います。あわせて継承を禁じるsealed、定義を分割するpartialも学びます。

図解

flowchart TB
    O["object(すべての型の親)"] --> M["ToString() / Equals() / GetHashCode()"]
    M --> D["既定は参照(同じインスタンスか)で比較"]
    D --> OV["override すると<br/>「中身が同じなら等しい」に変えられる"]
    style OV fill:#e8f5e9

サンプル

class Money
{
    public int Amount { get; }
    public Money(int amount) => Amount = amount;

    // 「金額が同じなら等しい」と定義する
    public override bool Equals(object? obj) => obj is Money m && m.Amount == Amount;
    // Equals を変えたら GetHashCode も揃える(HashSet/Dictionary のため)
    public override int GetHashCode() => Amount.GetHashCode();
    // 表示も分かりやすく
    public override string ToString() => $"{Amount}円";
}

var a = new Money(100);
var b = new Money(100);

Console.WriteLine(a.Equals(b));   // True(中身が同じ)
Console.WriteLine(a);             // 100円(ToStringが効く)

// GetHashCode を揃えたので、集合でも「同じ100円」として扱える
var set = new HashSet<Money> { a, b };
Console.WriteLine(set.Count);     // 1
  • すべての型はobjectを継承し、ToString/Equals/GetHashCodeを持つ
  • 既定は参照の比較(同じインスタンスか)。overrideで「中身が同じなら等しい」に変えられる
  • Equalsを変えたら必ずGetHashCodeも揃えるHashSet/Dictionaryが正しく動くため)
  • sealed classは継承を禁止、partial classクラス定義を複数ファイルに分割できる(自動生成コードとの併用で頻出)

演習

var p1 = new Point(1, 2);
var p2 = new Point(1, 2);

// TODO: Point の Equals をオーバーライドし、X と Y が同じなら等しいと判定させてください
//       (p1.Equals(p2) が True になる)
Console.WriteLine(p1.Equals(p2));

class Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) { X = x; Y = y; }
    ___
}
  • 期待される出力: True
ヒント1を見る

public override bool Equals(object? obj) => obj is Point p && p.X == X && p.Y == Y;

ヒント2を見る

上の1行をPointクラスの中に加えます

まとめ

  • すべての型はobjectを継承し、ToString/Equals/GetHashCodeを持つ
  • 「中身が同じ=等しい」にしたいならEqualsGetHashCodeをセットでオーバーライド
  • sealedは継承禁止、partialは定義の分割

次回: 添字アクセスや+を自作型に持たせる「インデクサーと演算子オーバーロード」です。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。