Вариативность делегатов в C#
У делегата параметр типа на входе ведёт себя как in, а тип
результата - как out. Делегат, который принимает более широкий
тип, подходит там, где собираются передать более узкий. Делегат,
который возвращает более узкий тип, подходит там, где ждут более
широкий результат.
Делегат для object можно сохранить в переменную делегата для string. Строка всё равно передаётся как объект. Обратная запись не компилируется: делегат для строки не примет произвольный объект:
Action<object> log = o => Console.WriteLine(o);
Action<string> use = log;
use("trace");
С результатом направление обратное. Делегат, который возвращает строку, сохраняют в переменную делегата, возвращающего объект:
Func<string> read = () => "done";
Func<object> box = read;
Console.WriteLine(box());
Сохраните делегат, который принимает object и проверяет, что значение является строкой, в переменную делегата для string. Проверьте строку "ok" и выведите результат.