Ковариантность делегата
В объявлении delegate можно пометить параметры
типа: in T - контравариантный аргумент,
out TResult - ковариантный результат. Тогда
делегат с более широким типом аргумента можно
присвоить переменной с более узким, а делегат с
более узким результатом - переменной с более широким
возвратом. Это правила для самого delegate,
не для IEnumerable<T> и других интерфейсов.
Синтаксис
delegate void Sink<in T>(T value);
delegate TResult Source<out TResult>();
Пример
Давайте присвоим делегат с in и более широким аргументом:
using System;
delegate void Sink<in T>(T value);
class Program
{
static void WriteObject(object value)
{
Console.WriteLine(value);
}
static void Main()
{
Sink<object> wide = WriteObject;
Sink<string> narrow = wide;
narrow("abcde");
}
}
Результат выполнения кода:
"abcde"
Пример
Давайте присвоим делегат с out и более узким результатом:
using System;
delegate TResult Source<out TResult>();
class Program
{
static void Main()
{
Source<string> narrow = () => "abcde";
Source<object> wide = narrow;
Console.WriteLine(wide());
}
}
Результат выполнения кода:
"abcde"
Пример
Давайте передать контравариантный делегат в метод:
using System;
delegate void Sink<in T>(T value);
class Program
{
static void Run(Sink<string> handler)
{
handler("12345");
}
static void WriteObject(object value)
{
Console.WriteLine(value);
}
static void Main()
{
Sink<object> wide = WriteObject;
Run(wide);
}
}
Результат выполнения кода:
"12345"