Func <T> con parametro out


167

Posso passare un metodo con un parametro out come Func?

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

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

Func ha bisogno di un tipo in modo che out non si compili lì, e chiamando listFunction richiede un int e non consentirà un out in.

C'è un modo per fare questo?

Risposte:


228

refe outnon fanno parte della definizione del parametro type, quindi non è possibile utilizzare il Funcdelegato incorporato per passare refe outargomenti. Certo, puoi dichiarare il tuo delegato se vuoi:

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

7
In C # 4 (2010) e versioni successive (non è stato rilasciato quando hai scritto la tua risposta) è possibile contrassegnare Tcome contraddittorio e Vcome covariante. Tuttavia, poiché un parametro ( output) di tipo Uviene passato per riferimento , Unon può essere contrassegnato come co o contraddittorio e deve rimanere "invariante". Quindi considera public delegate V MyDelegate<in T, U, out V>(T input, out U output);se usi C # 4 o versioni successive.
Jeppe Stig Nielsen,


24

Perché non creare una classe per incapsulare i risultati?

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

13

La Funcfamiglia dei delegati (o del Actionresto) non sono altro che semplici tipi di delegati dichiarati come

//.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)

ecc. I delegati in quanto tali possono avere parametri out / ref, quindi nel tuo caso è solo una questione di implementazione personalizzata da parte tua, come hanno sottolineato altre risposte. Per quanto riguarda il motivo per cui Microsoft non ha impacchettato questo per impostazione predefinita, pensa al semplice numero di combinazioni che richiederebbe.

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)

per solo due parametri. Non ci siamo nemmeno toccati ref. In realtà sarebbe ingombrante e confuso per gli sviluppatori.


2
Si noti che il sovraccarico della funzione C # non è in grado di distinguere tra delegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj)e delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj). Quindi oltre al numero di sovraccarichi il nome del simbolo è un altro motivo per cui Microsoft non ha potuto aggiungere questi sovraccarichi di Func.
Kasper van den Berg,

Qualcuno può riferirmi ad un articolo MSDN sui delegati sopra?
Su Llewellyn,

@SuLlewellyn Non sono riuscito a trovare l'articolo msdn originale, ma potresti provare: docs.microsoft.com/en-us/dotnet/api/… , docs.microsoft.com/en-us/dotnet/api/…
nawfal

0

Potresti avvolgerlo in un metodo lambda / delegate / function / che ha esposto l'interfaccia giusta e chiamato FindForBar, ma sospetto che FindForBar abbia considerato un parametro out come motivo, quindi dovresti essere sicuro di buttare via quelle informazioni ok / sicuro / desiderabile / aveva i risultati giusti (dovresti esserne sicuro anche se potessi passare direttamente a FindForBar).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.