Функція <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.