ジェネリッククラス
再利用可能なコンテナー型を作成します。
「ジェネリッククラス」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
ジェネリッククラスとは
ジェネリッククラスでは、クラス名の後ろの山かっこ内に1つ以上の型パラメーターを宣言します。これらのパラメーターは、クラス全体でフィールド、プロパティ、メソッドシグネチャ、戻り値の型に使用できます。
これにより、強い型付けを保ちながら、さまざまな要素型に対応する1つのコンテナーやサービスを記述できます。
class Box<T>
{
public T Value { get; set; }
}ジェネリッククラスのインスタンス化
インスタンスを作成するには、具体的な型引数を指定します。Box<int> と Box<string> は、構築された別々の型です。
それぞれの構築型は、あらゆる場所で T が実際の型に置き換えられたかのように動作します。
using System;
class Box<T> { public T Value { get; set; } }
class Program
{
static void Main()
{
var b = new Box<int> { Value = 7 };
Console.WriteLine(b.Value);
}
}ジェネリックなフィールドとプロパティ
型パラメーターは、フィールドやプロパティの型として使用できます。スタック、キュー、キャッシュでは、T の配列やリストにデータを格納することがよくあります。
内部ストレージは、キャストなしで型安全に保たれます。
class Pair<T>
{
public T First;
public T Second;
}複数の型パラメーター
クラスには複数の型パラメーターを指定できます。キーと値のペアやディクショナリ形式の型では、一般的に2つの型パラメーターを使用します。
複数の型パラメーターがある場合は、TKey や TValue のような説明的な名前を付けると、読みやすくなります。
class Entry<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Value { get; set; }
}シンプルなジェネリックスタック
ここでは、List<T> を基にした小さなジェネリックスタックを作成します。Push は末尾に追加し、Pop は末尾から削除します。
同じクラスで、整数、文字列、その他の任意の参照型や値型を扱えます。
using System;
using System.Collections.Generic;
class MyStack<T>
{
private readonly List<T> items = new();
public void Push(T item) => items.Add(item);
public T Pop()
{
var i = items[^1];
items.RemoveAt(items.Count - 1);
return i;
}
}
class Program
{
static void Main()
{
var s = new MyStack<string>();
s.Push("a");
s.Push("b");
Console.WriteLine(s.Pop());
}
}ジェネリッククラス内のジェネリックメソッド
ジェネリッククラスでは、個々のメソッドに追加の型パラメーターを宣言することもできます。メソッドレベルの型パラメーターは、クラスレベルの型パラメーターとは独立しています。
これにより、たとえば格納されている型を別の型に変換するなど、柔軟性が高まります。
class Box<T>
{
public T Value;
public TOut Map<TOut>(Func<T, TOut> f) => f(Value);
}クラスの制約
メソッドと同様に、ジェネリッククラスでも where を使って型パラメーターに制約を付けられます。制約は、そのパラメーターを使用するすべてのメンバーに適用されます。
以下では、where T : class により、null の代入と参照比較が可能になります。
class Repository<T> where T : class
{
private T current;
public bool IsEmpty => current is null;
}静的メンバーは型ごとに存在する
構築されたジェネリック型ごとに、静的フィールドの独自のコピーが作成されます。Counter<int> と Counter<string> は、それぞれ別のカウントを管理します。
これは、非ジェネリッククラスとの重要で見落としやすい違いです。
class Counter<T>
{
public static int Count;
}ジェネリッククラスでの既定値
ジェネリッククラス内では、T 型のフィールドに初期値が必要になることがよくあります。default(T) を使うか、型がコンテキストからわかる場合は短い default を使います。
参照型の場合は null、値型の場合はゼロ値になります。
class Slot<T>
{
public T Value = default!;
public bool HasValue { get; private set; }
}ジェネリッククラスの継承
ジェネリックな基底クラスを継承できます。サブクラスで型引数を固定することも、サブクラス自体をジェネリックのままにすることもできます。
型引数を固定すると基底クラスを特化でき、ジェネリックのままにするとパラメーターを上位へ引き継げます。
class Box<T> { public T Value; }
class IntBox : Box<int> { }
class NamedBox<T> : Box<T> { public string Name; }ジェネリックと組み込みコレクション
.NET の基本ライブラリには、List<T>、Dictionary<TKey, TValue>、Queue<T> など、多数のジェネリッククラスがあります。これらは、ジェネリッククラス設計の実用的な成果です。
独自のジェネリック型を記述することで、同じ安全で再利用可能なスタイルを拡張できます。
using System.Collections.Generic;
var scores = new Dictionary<string, int>();
scores["ada"] = 95;理解度チェック
ジェネリッククラスについての理解度を確認しましょう。
まとめ
ジェネリッククラスでは、クラス名の後ろに型パラメーターを宣言し、それをフィールド、プロパティ、メソッドに使用します。具体的な型引数を指定してインスタンス化すると、別々の型が作成されます。
ジェネリッククラスにはメソッドレベルの型パラメーターを追加したり、where 制約を付けたりできます。また、継承したり、型ごとの静的状態を保持したりすることもできます。組み込みコレクションはその代表例です。
よくある質問
「ジェネリッククラス」レッスンは無料ですか?
はい。「ジェネリッククラス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「ジェネリッククラス」で何を学びますか?
再利用可能なコンテナー型を作成します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「ジェネリッククラス」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- ジェネリックメソッド
- ジェネリッククラス
- where制約
- ジェネリックインターフェース