0Pricing
C# Academy · レッスン

where制約

型パラメーターを制約します。

「where制約」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

制約が存在する理由

既定では、型パラメーター T はほぼ object と同じように扱われるため、コンパイラーが許可できる操作はごくわずかです。where を使って記述する制約により、T に関する情報をコンパイラーに伝えられます。

その情報があれば、メソッドの呼び出し、インスタンスの作成、値の比較を安全に行えます。

void Show<T>(T value) where T : IFormattable
{
    // now ToString(format, provider) is available
}

インターフェイス制約

インターフェイス制約により、T が指定したインターフェイスを実装していることを要求できます。これにより、メソッド本体でそのインターフェイスのメンバーを呼び出せます。

以下では、where T : IComparable<T> により、CompareTo メソッドが存在することが保証されます。

T Max<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) >= 0 ? a : b;

基底クラス制約

T が特定の基底クラスを継承していることを要求できます。これにより、ジェネリックコード内でその基底型のメンバーを使用できます。

これは、すべてのエンティティが基底型を共有するフレームワークでよく使われます。

class Animal { public string Name = ""; }

string NameOf<T>(T a) where T : Animal => a.Name;

class 制約

where T : class により、T が参照型であることを要求します。これにより、null の代入と参照等価性のチェックが可能になります。

リポジトリ、キャッシュ、そして null を許容する参照を格納するもの全般でよく使われます。

T? FindOrNull<T>(bool found, T value) where T : class
    => found ? value : null;

struct 制約

where T : struct により、T が null 非許容の値型であることを要求します。これにより、T を値型として扱い、T? を null 許容値型として使用できます。

数値、列挙型、または小さな構造体だけを扱うヘルパーで使われます。

T? AsNullable<T>(T value) where T : struct
    => value;

new() 制約

new() 制約により、T にパブリックな引数なしコンストラクターがあることを要求します。これにより、メソッド本体で new T() と記述できます。

ファクトリやオブジェクトプールでは、ジェネリックにインスタンスを作成するためにこの制約を利用します。

using System;

class Program
{
    static T Make<T>() where T : new() => new T();

    static void Main()
    {
        var list = Make<System.Collections.Generic.List<int>>();
        Console.WriteLine(list.Count);
    }
}

制約の組み合わせ

1つのパラメーターに複数の制約を適用できます。記述順序は、最初に class または struct、次に基底クラス、その後にインターフェイス、最後に new() とする必要があります。

制約は1つの where の後に、コンマで区切って列挙します。

T Build<T>() where T : class, IComparable<T>, new()
    => new T();

複数の where 句

メソッドやクラスに複数の型パラメーターがある場合は、それぞれに独自の where 句を指定します。各句は続けて記述します。

これにより、各パラメーターの制約を明確に分けて管理できます。

TResult Convert<TInput, TResult>(TInput x)
    where TInput : class
    where TResult : new()
    => new TResult();

制約を使った実行可能な例

この完全なプログラムでは、IComparable<T> 制約を使って2つの値の大きい方を見つけます。整数と文字列の両方で動作します。

この制約があるため、メソッド内で CompareTo を呼び出せます。

using System;

class Program
{
    static T Max<T>(T a, T b) where T : IComparable<T>
        => a.CompareTo(b) >= 0 ? a : b;

    static void Main()
    {
        Console.WriteLine(Max(3, 9));
        Console.WriteLine(Max("apple", "pear"));
    }
}

notnull と unmanaged の制約

新しい C# では、さらに多くの制約が追加されています。where T : notnull は null 許容型を禁止するため、ディクショナリのキーに便利です。where T : unmanaged は、低レベルコードで使用する blittable な値型に T を限定します。

これらは、特定の用途における安全性をさらに高めます。

void Use<T>(T key) where T : notnull { }

unsafe void Raw<T>(T v) where T : unmanaged { }

制約は能力を制限するのではなく、可能にする

制約は制限のように見えますが、実際には機能を利用可能にします。制約がなければ T に対してほとんど何もできませんが、制約を付けるとそのメンバーを利用できるようになります。

アルゴリズムの動作に必要な最小限の制約を選び、型パラメーターをできるだけ柔軟に保ちましょう。

// No constraint: only object members available
string Name<T>(T x) => x.ToString();

理解度チェック

where 制約についての理解度を確認しましょう。

まとめ

where 句は、インターフェイス、基底クラス、class、struct、new()、notnull、unmanaged などの制約を型パラメーターに付けます。それぞれの制約によって、T に対して特定の操作が可能になります。

制約を正しい順序で並べ、パラメーターごとに1つの句を使い、アルゴリズムに必要な最小限の制約を選びましょう。

よくある質問

「where制約」レッスンは無料ですか?

はい。「where制約」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「where制約」で何を学びますか?

型パラメーターを制約します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「where制約」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ジェネリックメソッド
  2. ジェネリッククラス
  3. where制約
  4. ジェネリックインターフェース
← C# Academyに戻る