Menu
CoddyTech

ジェネリクス (クラスとメソッド)

CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 42/70。

ジェネリクスを使うと、型安全性を保ちながら、あらゆるデータ型で動作するクラスやメソッドを記述できます。IntList、StringList、DoubleListそれぞれに別々のクラスを書く代わりに、それらすべてを扱うジェネリッククラスを1つ書けばよいのです。

ジェネリッククラスは型パラメーターを使用します。通常は T という名前で、山かっこで囲みます。

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

// 異なる型での使用
Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Box<int>を作成すると、コンパイラはすべてのTをintに置き換えます。これにより、コンパイル時に型チェックが行われます。誤ってintのボックスに文字列を格納することはありません。

ジェネリックメソッドも同様に機能し、1つのメソッドで異なる型を扱えます。

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // x=2, y=1

コンパイラーは引数から型を推論するため、Swap<int>を明示的に書く必要はありません。ジェネリックはList<T>やDictionary<TKey, TValue>のようなコレクションの基盤であり、再利用可能で型安全なコードを実現します。

challenge icon

チャレンジ

簡単

任意の型の項目を保持して管理できるジェネリックなStorage<T>システムを作りましょう。再利用可能なコンテナークラスを作成して、ジェネリクスの力を確かめます。一度書けば、整数、文字列、その他どのような型にも使えます!

コードを2つのファイルに分けて整理します。

  • Storage.cs:DataStorage名前空間にジェネリックなStorage<T>クラスを作成します。このストレージコンテナーには、次の機能が必要です。
    • 項目を保持する型Tのプライベート配列と、格納されている項目数を追跡するCountプロパティを持つ
    • コンストラクターで容量を受け取り、内部配列を初期化する
    • 空きがある場合に項目を追加するAdd(T item)メソッドを持つ
    • 指定されたインデックスの項目を返すGet(int index)メソッドを持つ
    • 格納されているすべての項目を", "で結合して返すGetAll()メソッドを持つ
  • Program.cs:メインファイルでは、異なる2つの型でジェネリッククラスが動作することを示します。Storage<int>とStorage<string>を作成して、それぞれに項目を追加し、同じクラスが両方の型で問題なく使えることを示してください。

入力は4つ与えられます。

  • 格納する1つ目の整数
  • 格納する2つ目の整数
  • 格納する1つ目の文字列
  • 格納する2つ目の文字列

容量が5の整数用ストレージと、容量が5の文字列用ストレージを作成します。2つの整数を整数用ストレージに、2つの文字列を文字列用ストレージに追加してください。

次の形式で出力してください。

Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}

たとえば、入力が42、100、Hello、Worldの場合、出力は次のようになります。

Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello

Storage<T>クラスは一度書くだけで、intとstringの両方で問題なく動作します。これがジェネリクスの魅力です!コンパイラーが型の安全性を保証するため、誤って文字列を整数用ストレージに追加することはできません。

自分で試してみよう

using System;
using DataStorage;

class Program
{
    public static void Main(string[] args)
    {
        // 入力を読み取る
        int num1 = Convert.ToInt32(Console.ReadLine());
        int num2 = Convert.ToInt32(Console.ReadLine());
        string str1 = Console.ReadLine();
        string str2 = Console.ReadLine();

        // TODO: 容量5のStorage<int>を作成する
        
        // TODO: 2つの整数を整数用ストレージに追加する
        
        // TODO: 容量5のStorage<string>を作成する
        
        // TODO: 2つの文字列を文字列用ストレージに追加する
        
        // TODO: 指定された形式で出力する
        // Int storage: {GetAll()}
        // 整数の個数: {Count}
        // 最初の整数: {Get(0)}
        // String storage: {GetAll()}
        // String count: {Count}
        // First string: {Get(0)}
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C#オンラインコンパイラ