インターフェースとデリゲートにおける変性(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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- ジェネリックメソッド/型と制約
- インターフェースとデリゲートにおける変性(in/out)
- Nullable reference types(認識)と注釈(C# 6パターン)