1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

基底クラスのリストに派生クラスのオブジェクトを入れる時に気を付けたい点

Last updated at Posted at 2024-01-28

独自クラスのオブジェクトをリストに入れたりする処理を実装してて、タイトルのように、基底クラスのリストに派生クラスのオブジェクトが入ることに気付きました。そこで、自分なりに注意したいと思ったことを軽くまとめてみました。

まず、名前だけを持つUserクラスと、これを継承して名前と住所を持つ派生クラスを用意します。

class User
{
    internal string name { get; set; }
}

class User2 : User
{
    internal string address { get; set; }
}

そして、Userクラスのリストを用意します。

List<User> userList = new List<User>();

ここで用意したuserListUserクラスのオブジェクトが入るのは、まぁそりゃそうだよねと言った感じですね。

User user = new User
{
    name = "testName"
};
userList.Add(user);
Console.WriteLine(userList[0].name); // testName

それでもって、同じuserListUser2クラスのオブジェクトも入ってしまうということで、おやおや?と思った次第です。

User2 user2 = new User2
{
    name = "testName2",
    address = "testAddress"
};
userList.Add(user2);
Console.WriteLine(userList[1].name); // testName2

ただ、userList[1]からUser2クラスにしかないaddressを参照しようとすると、コンパイラエラーが発生してしまいます。

Console.WriteLine(userList[1].address); // Compiler Error CS1061

基底クラスのオブジェクトと派生クラスのオブジェクト両方とも登場する可能性があるときは、型変換や型パターンマッチングを入れた方が良いと感じました。

型を変換する

使いたいオブジェクトのクラスが明確なら、キャスト式で変換する。

// userList[1]は、User2クラス!
Console.WriteLine(((User2)userList[1]).address); // testAddress

もしも、UserクラスのオブジェクトをUser2クラスに変換しようとすると、System.InvalidCastExceptionが発生してしまう。
そのため、どのクラスのオブジェクトが来るか分からない時は型パターンマッチングも入れるべきだと思いました。

型パターンマッチング

Userクラスのオブジェクトはnameだけ出力、User2クラスのオブジェクトは、nameaddressを表示させる。

foreach (User user in userList)
{
    Console.WriteLine(user.name);

    if (user is User2)
    {
        Console.WriteLine(((User2)user).address); // ちゃんとキャスト式で変換してあげる
    }
}

※コメントで頂いた書き方をここに追記します。

foreach (User user in userList)
{
    Console.WriteLine(user.name);

    if (user is User2 user2) // ここで変数名を決められる
    {
        Console.WriteLine(user2.address);
    }
}

何のクラスのオブジェクトなのか分かるような変数名にしてあげると、後の処理でどんなオブジェクトを扱ってるのか追いやすくなってイイ感じになりそうだなと思いました。

switchでも、case User2 user2:のように、変数名を決められるようです。

最後に

なるべくキャスト式を用いることで、実装者がどんなオブジェクトが来る想定で実装したのか明確になるのではないかと感じました。また、型パターンマッチングも用いることで、より安全な実装になるのではないかと感じました。

Qiita初投稿です。記事の質はまだまだですが、アドバイスや意見などあれば、コメントを頂けると助かります。
今年はアウトプットを意識してエンジニアライフを楽しもうと思います。

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?