Funktion <T> ohne Parameter out

167

Kann ich eine Methode mit einem out-Parameter als Func übergeben?

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

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

Func benötigt einen Typ, damit out dort nicht kompiliert wird, und der Aufruf von listFunction erfordert ein int und erlaubt kein out in.

Gibt es eine Möglichkeit, dies zu tun?

blau
quelle

Antworten:

228

refund outsind nicht Teil der Typparameterdefinition, sodass Sie den integrierten FuncDelegaten nicht zum Übergeben refund für outArgumente verwenden können. Natürlich können Sie Ihren eigenen Delegierten deklarieren, wenn Sie möchten:

delegate V MyDelegate<T,U,V>(T input, out U output);
Mehrdad Afshari
quelle
7
In C # 4 (2010) und höher (wurde nicht veröffentlicht, als Sie Ihre Antwort geschrieben haben) ist es möglich, Tals kontravariante und Vals kovariante zu markieren . Da jedoch ein Parameter ( output) vom Typ Uals Referenz übergeben wird , Ukann er nicht als co- oder kontravariant markiert werden und muss "invariant" bleiben. Überlegen public delegate V MyDelegate<in T, U, out V>(T input, out U output);Sie also, ob Sie C # 4 oder höher verwenden.
Jeppe Stig Nielsen
24

Warum nicht eine Klasse erstellen, um die Ergebnisse zu kapseln?

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

Die FuncFamilie der Delegierten (oder auch nur Action) sind nichts anderes als einfache Delegiertypen, die wie folgt deklariert sind

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

usw. Delegierte als solche können out / ref-Parameter haben. In Ihrem Fall handelt es sich also nur um eine benutzerdefinierte Implementierung durch Sie selbst, wie andere Antworten gezeigt haben. Überlegen Sie sich, warum Microsoft dies nicht standardmäßig verpackt hat, wie viele Kombinationen erforderlich sind.

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)

für nur zwei Parameter. Wir haben nicht einmal berührt ref. Es wäre für Entwickler tatsächlich umständlich und verwirrend.

nawfal
quelle
2
Beachten Sie, dass die Überladung der C # -Funktion nicht zwischen delegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj)und unterscheiden kann delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj). Neben der Anzahl der Überladungen sind Symbolnamen ein weiterer Grund, warum Microsoft diese Überladungen von nicht hinzufügen konnte Func.
Kasper van den Berg
Kann mich jemand auf einen MSDN-Artikel über die oben genannten Delegierten verweisen?
Su Llewellyn
@SuLlewellyn Ich konnte den ursprünglichen msdn-Artikel nicht finden, aber Sie könnten versuchen: docs.microsoft.com/en-us/dotnet/api/… , docs.microsoft.com/en-us/dotnet/api/…
nawfal
0

Sie könnten es in ein Lambda / Delegate / Funktion / Methode einbinden, das die richtige Schnittstelle und den Namen FindForBar verfügbar macht, aber ich vermute, dass FindForBar als Grund als out-Parameter gezählt hat, sodass Sie sicher sein müssen, dass diese Informationen weggeworfen wurden ok / sicher / wünschenswert / hatte die richtigen Ergebnisse (Sie müssten sich dessen sicher sein, auch wenn Sie FindForBar direkt übergeben könnten).

Logan Capaldo
quelle