Функція <T> з параметром out


167

Чи можу я передати метод із параметром out як Func?

public IList<Foo> FindForBar(string bar, out int count) { }

// somewhere else
public IList<T> Find(Func<string, int, List<T>> listFunction) { }

Func потребує типу, щоб його не компілювали там, а для виклику listFunction потрібен int і не дозволить вийти в.

Чи є спосіб це зробити?

Відповіді:


228

refі outне є частиною визначення параметра типу, тому ви не можете використовувати вбудований Funcделегат для передачі refта outаргументів. Звичайно, ви можете оголосити власного делегата, якщо хочете:

delegate V MyDelegate<T,U,V>(T input, out U output);

7
У C # 4 (2010) і пізніше (не було випущено, коли ви писали свою відповідь) можна позначити Tяк противаріантний і Vковаріантний. Однак, оскільки параметр ( output) типу Uпередається за посиланням , Uне може бути позначений ко- або противаріантним і повинен залишатися "інваріантним". Тому подумайте, public delegate V MyDelegate<in T, U, out V>(T input, out U output);чи використовуєте ви C # 4 або новішу версію.
Jeppe Stig Nielsen


24

Чому б не створити клас, щоб інкапсулювати результати?

public class Result
{
     public IList<Foo> List { get; set; }
     public Int32 Count { get; set; }
}

13

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. Це було б насправді громіздким і заплутаним для розробників.


2
Зауважте, що перевантаження функції C # не може розрізняти delegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj)та delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj). Тому, крім кількості символу перевантаження, назва другої причини, чому Microsoft не може додати ці перевантаження Func.
Каспер ван ден Берг

Чи може хтось посилати мене на статтю MSDN про делегатів вище?
Su Llewellyn

@SuLlewellyn Я не зміг знайти оригінальну статтю msdn , але ви можете спробувати: docs.microsoft.com/en-us/dotnet/api/… , docs.microsoft.com/en-us/dotnet/api/…
nawfal

0

Ви можете обернути його в лямбда / делегат / функцію / метод, який відкрив правильний інтерфейс і назвав FindForBar, але я підозрюю, що FindForBar вважає причиною вихідний параметр, тому вам потрібно буде впевнено відкидати цю інформацію ОК / безпечний / бажаний / мав правильні результати (ви повинні бути впевнені в цьому, навіть якщо ви могли просто пройти безпосередньо в FindForBar).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.