Func
семейства делегатов (или Action
по этому вопросу) ничего, кроме простых типов делегатов, объявленных как
//.NET 4 and above
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T obj)
//.NET 3.5
public delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
public delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)
и т.д. Делегаты как таковые могут иметь параметры out/ref, поэтому в вашем случае это только вопрос индивидуальной реализации, как указывали другие ответы. Что касается того, почему Microsoft не упаковывала это по умолчанию, подумайте о большом количестве комбинаций, которые потребуются.
delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(T1 obj1, out T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, out T2 obj2)
всего два параметра. Мы даже не коснулись ref
. Это на самом деле было бы громоздким и запутанным для разработчиков.
В случае, если кто-то смущен, как и я, вы не имеете *, чтобы называть своего делегата «Func», как встроенные ... – Dunc
@ Dunc - Исправлено. Я бы смутился, если бы не ваш комментарий. –
В C# 4 (2010) и позже (не был выпущен, когда вы написали свой ответ), можно пометить 'T' как контравариантную, а' V' - ковариантной. Однако, поскольку параметр ('output') типа' U' передается *** по ссылке ***, 'U' не может быть отмечен ко- или контравариантным и должен оставаться« инвариантным ». Поэтому рассмотрим 'public delegate V MyDelegate (вход T, выход U);' если вы используете C# 4 или новее. –