0Pricing
C# Academy · レッスン

インターフェースとデリゲートにおける変性(in/out)

C#の変性を理解します。インターフェースとデリゲートで、プロデューサー(共変)には out 、コンシューマー(反変)には in を使います。

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

変性の概要

変性を使用すると、ジェネリックインターフェイスやデリゲートを継承関係とともに扱えます。

  • out = 共変(プロデューサー)
  • in = 反変(コンシューマー)
  • T を生成するだけ、または消費するだけの API であれば安全です

共変性の例

IEnumerable<out T> は共変です。Cat のシーケンスは、Animal のシーケンスが必要な場所で使用できます。

using System;
using System.Collections.Generic;

public class Animal { public virtual string Name() { return "animal"; } }
public class Cat : Animal { public override string Name() { return "cat"; } }

public class Program
{
  static void PrintAll(IEnumerable<Animal> animals)
  {
    foreach (Animal a in animals)
    {
      Console.WriteLine(a.Name());
    }
  }

  public static void Main(string[] args)
  {
    List<Cat> cats = new List<Cat>();
    cats.Add(new Cat());
    // IEnumerable<Cat> -> IEnumerable<Animal> is allowed (out T)
    PrintAll(cats);
  }
}

反変性の例

IComparer<in T> は反変です。Animal 用の比較器は、T を単に受け取るだけなので、Cat に対しても機能します。

using System;
using System.Collections.Generic;

public class Animal { public string N; public Animal(string n){ N=n; } }
public class Cat : Animal { public Cat(string n) : base(n) {} }

// Comparer can compare any Animals
public class AnimalNameComparer : IComparer<Animal>
{
  public int Compare(Animal x, Animal y)
  {
    return string.Compare(x == null ? "" : x.N, y == null ? "" : y.N, StringComparison.Ordinal);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    List<Cat> cats = new List<Cat>();
    cats.Add(new Cat("Miso"));
    cats.Add(new Cat("Ada"));
    // IComparer<Animal> can be used as IComparer<Cat> (in T)
    cats.Sort(new AnimalNameComparer());
    foreach (Cat c in cats) Console.WriteLine(c.N);
  }
}

デリゲートの変性

デリゲートも変性を持ちます。Func<out TResult> はプロデューサー、Action<in T> はコンシューマーです。

using System;

public class Animal { public virtual string Speak(){ return "???"; } }
public class Cat : Animal { public override string Speak(){ return "meow"; } }

public class Program
{
  static Animal MakeAnimal() { return new Animal(); }
  static void HandleAnimal(Animal a) { Console.WriteLine(a.Speak()); }

  public static void Main(string[] args)
  {
    // Func<Cat> can be used where Func<Animal> is expected? Yes, because TResult is out.
    Func<Animal> maker = new Func<Cat>(delegate { return new Cat(); });
    Console.WriteLine(maker().Speak());

    // Action<Animal> can be used where Action<Cat> is expected? Yes, because T is in.
    Action<Cat> catSink = new Action<Animal>(HandleAnimal);
    catSink(new Cat());
  }
}

カスタム変性インターフェイス

設計ルールとして、プロデューサー専用の型パラメーターにはout、コンシューマー専用の型パラメーターにはinを付けると、安全な変換を有効にできます。

using System;

// Producer-only interface: out T
public interface ISource<out T>
{
  T Get();
}

// Consumer-only interface: in T
public interface ISink<in T>
{
  void Put(T item);
}

public class Animal { public string N; }
public class Cat : Animal { }

public class CatSource : ISource<Cat>
{
  public Cat Get() { return new Cat(); }
}

public class AnimalSink : ISink<Animal>
{
  public void Put(Animal a) { Console.WriteLine("Got animal"); }
}

public class Program
{
  public static void Main(string[] args)
  {
    ISource<Animal> animals = new CatSource(); // out T allows upcast
    ISink<Cat> cats = new AnimalSink();        // in T allows down-assign
    animals.Get();
    cats.Put(new Cat());
  }
}

変性のヒント

ヒント:

  • out パラメーターは、出力位置(戻り値の型や共変な位置)にのみ記述できます。
  • in パラメーターは、入力位置(メソッドのパラメーター)にのみ記述できます。
  • 変性を宣言する際、同じ T を生成と消費の両方に使用しないでください。
  • 変性が適用されるのはインターフェイスとデリゲートであり、クラスには適用されません。

共変性のキーワード

簡単な確認です。インターフェイスまたはデリゲートの型パラメーターを共変にするキーワードはどれでしょうか?

まとめ

まとめ: インターフェイスとデリゲートでは、プロデューサー(共変性)にout、コンシューマー(反変性)にinを使用します。安全な変換を有効にするには、API の方向を一方向に保ってください。

よくある質問

「インターフェースとデリゲートにおける変性(in/out)」レッスンは無料ですか?

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

「インターフェースとデリゲートにおける変性(in/out)」で何を学びますか?

C#の変性を理解します。インターフェースとデリゲートで、プロデューサー(共変)には out 、コンシューマー(反変)には in を使います。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「インターフェースとデリゲートにおける変性(in/out)」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. ジェネリックメソッド/型と制約
  2. インターフェースとデリゲートにおける変性(in/out)
  3. Nullable reference types(認識)と注釈(C# 6パターン)
← C# Academyに戻る