ジェネリックインターフェース
型に依存しない抽象化を行います。
「ジェネリックインターフェース」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
ジェネリックインターフェイスとは
ジェネリックインターフェイスでは、名前の後ろの山かっこ内に型パラメーターを宣言します。実装する側が具体的な型を選択すると、それに応じてインターフェイスの契約も適応します。
.NET ライブラリでは、IEnumerable<T> や IComparable<T> など、ジェネリックインターフェイスが至るところで使われています。
interface IRepository<T>
{
void Add(T item);
T Get(int id);
}ジェネリックインターフェイスの実装
クラスは、具体的な型引数を指定することでジェネリックインターフェイスを実装できます。すると、メソッドシグネチャではその実際の型を使用します。
これにより、キャストなしで型安全かつ再利用可能な契約を実現できます。
using System.Collections.Generic;
class IntStore : IRepository<int>
{
private readonly List<int> data = new();
public void Add(int item) => data.Add(item);
public int Get(int id) => data[id];
}
interface IRepository<T>
{
void Add(T item);
T Get(int id);
}実装側でジェネリックのままにする
クラスは、ジェネリックインターフェイスに独自の型パラメーターを渡しながら、自身もジェネリックのまま実装できます。
これにより、任意の要素型で実装を再利用できます。
using System.Collections.Generic;
class Store<T> : IRepository<T>
{
private readonly List<T> data = new();
public void Add(T item) => data.Add(item);
public T Get(int id) => data[id];
}
interface IRepository<T> { void Add(T item); T Get(int id); }IComparable<T> の実例
IComparable<T> は組み込みのジェネリックインターフェイスです。これを実装すると、型のインスタンスの順序を定義でき、並べ替えが可能になります。
CompareTo メソッドは、負の値、0、または正の値を返します。
class Money : IComparable<Money>
{
public int Cents;
public int CompareTo(Money? other)
=> Cents.CompareTo(other?.Cents ?? 0);
}IEnumerable<T> の実装
IEnumerable<T> は、LINQ と foreach の中心となるインターフェイスです。これを実装する型は反復処理できます。多くの場合、内部コレクションのイテレーターに処理を委譲します。
yield return を使うイテレーターメソッドにより、簡単に実装できます。
using System.Collections;
using System.Collections.Generic;
class Bag<T> : IEnumerable<T>
{
private readonly List<T> items = new();
public void Add(T x) => items.Add(x);
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}実行可能なジェネリックインターフェイス
この完全なプログラムでは、ジェネリックな IPrinter<T> を定義し、文字列用に実装してから使用します。
インターフェイスにより、具体的な型にかかわらず Print メソッドが保証されます。
using System;
interface IPrinter<T> { void Print(T value); }
class ConsolePrinter<T> : IPrinter<T>
{
public void Print(T value) => Console.WriteLine(value);
}
class Program
{
static void Main()
{
IPrinter<string> p = new ConsolePrinter<string>();
p.Print("hello generics");
}
}out による共変性
out が付いたジェネリックインターフェイスの型パラメーターは共変です。これは出力位置にのみ現れます。これにより、IEnumerable<Cat> を IEnumerable<Animal> が必要な場所で使用できます。
共変性により、継承関係に沿った代入互換性が保たれます。
interface IProducer<out T>
{
T Produce();
}in による反変性
in が付いた型パラメーターは反変です。これは入力位置にのみ現れます。これにより、IComparer<Animal> を IComparer<Cat> が必要な場所で使用できます。
反変性により、コンシューマーに対する代入可能性の方向が反転します。
interface IConsumer<in T>
{
void Consume(T item);
}複数の型パラメーター
ジェネリックインターフェイスは、複数のパラメーターを受け取れます。IDictionary<TKey, TValue>は、キーの型と値の型を分けて指定する、よく知られた例です。
各パラメーターは、それぞれ独立して非変、共変、または反変にできます。
interface IMapper<TIn, TOut>
{
TOut Map(TIn input);
}インターフェイスに対してプログラミングする
具象クラスではなくジェネリックインターフェイスに依存すると、コードの柔軟性が高まります。呼び出し側を変更せずに実装を入れ替えられます。
IEnumerable<T>型のメソッドパラメーターは、リスト、配列、クエリ結果を同じように受け取れます。
using System.Collections.Generic;
using System.Linq;
int Total(IEnumerable<int> values) => values.Sum();ジェネリックインターフェイスによる制約
ジェネリックインターフェイスは、制約として頻繁に使用されます。where T : IComparable<T>によって、メソッドで入力を並べ替えたり比較したりできます。
これは2つのジェネリック機能を組み合わせ、安全で再利用可能なアルゴリズムを実現します。
T Min<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) <= 0 ? a : b;クイックチェック
ジェネリックインターフェイスについての理解度を確認しましょう。
まとめ
ジェネリックインターフェイスでは型パラメーターを宣言し、実装側でそれらを確定したり、そのまま引き継いだりできます。組み込みの例として、IEnumerable<T>、IComparable<T>、IDictionary<TKey, TValue>があります。
変性アノテーションのoutとinによって共変性と反変性を有効にでき、ジェネリックインターフェイスはwhere制約とも自然に組み合わせられます。
AI チューターと学ぶ C# — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 93
- レッスン
- 346
よくある質問
「ジェネリックインターフェース」レッスンは無料ですか?
はい。「ジェネリックインターフェース」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「ジェネリックインターフェース」で何を学びますか?
型に依存しない抽象化を行います。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「ジェネリックインターフェース」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- ジェネリックメソッド
- ジェネリッククラス
- where制約
- ジェネリックインターフェース