List型の変数をコンソール画面に表示させたい

int型やstring型のような組み込み型変数のようにコンソール画面に表示したい
今回は、実用はありませんがコードの学習も兼ねて実現する方法を考えてみます

普通に考える

int型やstring型のように記述

List型の変数をstring型やint型のようにコンソールに表示しようした場合、例えば次のようなコードでは、思わぬ結果となります

コード

List<int> scores = new() { 1, 2, 3, 4, 5 };
Console.WriteLine(scores);

表示

scores変数の型を表示しています

System.Collections.Generic.List`1[System.Int32]

期待した結果が得られる方法

次のようにListの内容を順番に表示すればいいですよね

コード

List<int> scores = new() { 1, 2, 3, 4, 5 };

foreach (var score in scores)
{
    Console.WriteLine(score);
}

または、

List<int> scores = new() { 1, 2, 3, 4, 5 };

// for文で実装
for (int i = 0; i < scores.Count; i++)
{
    Console.WriteLine(scores[i]);
}

表示

1
2
3
4
5

どうしても最初のような書き方をしたい

C#の機能を駆使して実現してみましょう
いくつかの知識が必要になります。どれくらい知っていますか?

使っている文法や機能(得られる知識)

変数(null許容型含む)、代入、初期化子

scoresが変数になります。
scores = new() { 1, 2, 3, 4, 5 };が初期化子です。変数に整数型のデータを代入しています

代入演算子(複合代入演算子含む)

msg += $"{this[i]}\n";の+=の部分になります。msg変数に追加するようにしています

文字列のエスケープシーケンス

\nの部分になります。改行することを表しています

コンソール画面への表示

Console.WriteLineメソッドの部分です

文字列補間

$"{x}"の部分です
変数のxがこの部分に差し込まれたものが文字列となります

繰り返し(for, foreach, List型のForEachメソッド)

forの部分です

List型

ExList<T>の部分です

インスタンスの参照

thisの部分です
これは、newで作成されたインスタンス(このサンプルでは、List型のscores変数)自体を指しています
頭の中で置き換えて考えてもいいです

インデクサー

this[I]の部分です
thisはインスタンス参照なので、scores[i]と同様になると考えてみましょう

ラムダ式

x => msg += $"{x}\n"の部分です

xには、scoresの内容が1つずつ順番に入ると考えます
msgには、xの情報が連結されていきます。連結されるたびに改行コードも追加されます
この式の実行では、ループごとに1つのデータが連結され、結果が戻されるようになります

オブジェクト指向

List scores = new() { 1, 2, 3, 4, 5 };のところになります
List scores = new List() { 1, 2, 3, 4, 5 };を省略したもので同じです
new演算子で、クラスからインスタンスを作成する考え方になります

クラス、メソッド

class ExListがクラス、public string ToString()がメソッドです

ルートクラス

ToString()がルートクラスであるObjectクラスのメソッドになります

継承

class ExList : Listの部分です

ポリモーフィズム

public override string? ToString()の部分です
難しいですよね。このToString()メソッドを呼び出すとObjectクラスのメソッドが呼び出されますがポリモーフィズムによって、ここで定義されているメソッドが呼び出されることになります

オーバーライド

public override string? ToString()の部分です
overrideキーワードの部分です。C#の場合、このキーワードを付けて上位継承元クラスのメソッドより優先的に実行するように指示します

自作クラスで、コンソール画面に表示する

次のコードを見てください。List<T>のところが、ExList<T>に置き換わっていますよね。
これだけで、Listの内容を表示できるようにしています
ExListクラスは.Netフレームワークではないので自作します

コード

// 整数の場合
ExList<int> scores = new() { 1, 2, 3, 4, 5 };
Console.WriteLine(scores);

// 文字列の場合
ExList<string> membersName = new() { "山田", "山本", "木下" };
Console.WriteLine(membersName);

表示

1
2
3
4
5

山田
山本
木下

上記表示のために作成するExList<T>クラス

List型<T>を継承して独自型を自作しています。List型の継承によって、List型が備えているメンバーを利用することができます。なので、List型と同じ使い方ができるわけです

class ExList<T> : List<T>
{
    public override string? ToString()
    {
        string? msg = null;

        // for文で実装
        for (int i = 0; i < Count; i++)
        {
            msg += $"{this[i]}\n";
        }
        return msg;
    }
}

おまけ

for文以外で実現した場合

// foreach文で実装
foreach (var item in this)
{
    msg += $"{item}\n";
}
// ForEachメソッドで実装
ForEach(x => msg += $"{x}\n");

.Net6のトップレベルステートメントで記述したコードのすべて

コンソールアプルの作成では、名前空間やクラス、Mainメソッド、usingの省略が可能です
内部では、しっかり上記は補間されているため、実行時は同じ動作になります

{
    List<int> scores = new() { 1, 2, 3, 4, 5 };
    Console.WriteLine(scores);
}
{
    List<int> scores = new() { 1, 2, 3, 4, 5 };

    // for文で実装
    for (int i = 0; i < scores.Count; i++)
    {
        Console.WriteLine(scores[i]);
    }
    // foreach文で実装
    foreach (var score in scores)
    {
        Console.WriteLine(score);
    }
    // (おまけ)ForEachメソッドで実装
    scores.ForEach(score => Console.WriteLine(score));
}
{
    // 整数の場合
    ExList<int> scores = new() { 1, 2, 3, 4, 5 };
    Console.WriteLine(scores);
}
{
    // 文字列の場合
    ExList<string> membersName = new() { "山田", "山本", "木下" };
    Console.WriteLine(membersName);
}

class ExList<T> : List<T>
{
    public override string? ToString()
    {
        string? msg = null;

        // for文で実装
        for (int i = 0; i < Count; i++)
        {
            msg += $"{this[i]}\n";
        }

        // foreach文で実装
        foreach (var item in this)
        {
            msg += $"{item}\n";
        }

        // ForEachメソッドで実装
        ForEach(x => msg += $"{x}\n");

        return msg;
    }
}

C#

Posted by hidepon