Ковариантность out
В объявлении интерфейса или делегата параметр
типа помечают ключевым словом out,
если T используется только как тип
результата (возвращаемое значение). Тогда
IRead<Cat> можно присвоить переменной
IRead<Animal> при наследовании
Cat : Animal - тип «расширяется»
к базовому. На входящих параметрах методов
out T ставить нельзя.
Синтаксис
interface IRead<out T>
{
T Read();
}
IRead<Базовый> box = new Реализация<Производный>();
Пример
Давайте присвоим IRead<Cat> переменной
IRead<Animal> и выведем имя:
using System;
interface IRead<out T>
{
T Read();
}
class Animal
{
public string Name = "animal";
}
class Cat : Animal
{
public Cat()
{
Name = "cat";
}
}
class Page : IRead<Cat>
{
public Cat Read()
{
return new Cat();
}
}
class Program
{
static void Main()
{
IRead<Animal> box = new Page();
Console.WriteLine(box.Read().Name);
}
}
Результат выполнения кода:
"cat"
Пример
Давайте сделаем обобщённую реализацию
IRead<T> и снова присвоим базовому
интерфейсу:
using System;
interface IRead<out T>
{
T Read();
}
class Animal
{
public string Name;
}
class Cat : Animal { }
class Page<T> : IRead<T> where T : Animal, new()
{
public T Read()
{
var item = new T();
item.Name = "abcde";
return item;
}
}
class Program
{
static void Main()
{
IRead<Animal> box = new Page<Cat>();
Console.WriteLine(box.Read().Name);
}
}
Результат выполнения кода:
"abcde"
Пример
При out T нельзя принимать T
в параметрах - такой интерфейс не компилируется:
interface IBad<out T>
{
void Store(T value);
}
Параметр T здесь входящий, поэтому
нужен in, а не out.
Смотрите также
-
контравариантность
in,
которая сужает тип во входящих параметрах -
наследование
inheritance,
без которого не сравниваютCatиAnimal -
интерфейс
interface,
где объявляютIRead<out T> -
параметр типа
type-param,
к которому добавляютout