2009-08-15 21 views
134

Kann ich eine Methode mit einem out-Parameter als Func übergeben?Func <T> ohne Parameter

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

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

Func braucht einen Typ, so wird aus nicht dort kompilieren, und ruft listFunction erfordert einen int und wird eine aus in nicht zulassen.

Gibt es eine Möglichkeit, dies zu tun?

Antwort

192

ref und out sind nicht Teil der Definition Typ-Parameter, so dass Sie nicht die eingebaute in Func delegieren können ref und out Argumente zu übergeben. Natürlich können Sie Ihre eigenen Delegierten erklären, wenn Sie wollen:

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

Falls jemand anders wie ich verwirrt ist, müssen Sie Ihren Delegierten nicht "Func" nennen, wie die eingebauten ... – Dunc

+0

@Dunc - Fixed. Ich wäre wirklich verwirrt gewesen, wäre da nicht Ihr Kommentar. –

+5

In C# 4 (2010) und später (wurde nicht veröffentlicht, als Sie Ihre Antwort geschrieben haben) ist es möglich, 'T' als kontravariante und' V' als kovariante zu markieren. Da jedoch ein Parameter ("output") vom Typ "U" durch *** *** übergeben wird, kann "U" nicht als co- oder kontravariant markiert werden und muss "invariant" bleiben. Betrachte also 'public delegate V MyDelegate (T input, out U output); 'wenn du C# 4 oder höher benutzt. –

19

Warum nicht eine Klasse zum Einkapseln der Ergebnisse erstellen?

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

Man könnte es in einem Lambda/Delegierten/Funktion/Methode wickeln, die die richtige Schnittstelle freigelegt und FindForBar genannt, aber ich vermute, dass FindForBar als out-Parameter als Grund zählen hat, so dass Sie bräuchten Achte darauf, dass diese Information weggeworfen wurde, war ok/sicher/wünschenswert/hatte die richtigen Ergebnisse (du musst dir das sicher sein, selbst wenn du FindForBar einfach direkt weitergeben könntest).

9

Die Func Familie von Delegierten (oder Action was das betrifft) sind nichts anderes als einfache Delegattypen erklärt wie

//.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. Die Delegierten als solche kann out/ref Parameter haben, so in Ihrem Fall ist es nur eine Frage der benutzerdefinierten Umsetzung von Ihnen selbst, wie andere Antworten darauf hingewiesen haben. Warum Microsoft das nicht standardmäßig gepatcht hat, denken Sie an die schiere Anzahl der Kombinationen, die es erfordern würde.

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.

+1

Beachten Sie, dass das Überladen der C# -Funktion nicht zwischen "delegate TResult Func (T1 obj, T2 obj)" und "delegate TResult Func (aus T1 obj, T2 obj)" unterscheiden kann. Neben der Anzahl der Überladungen ist der Symbolname ein weiterer Grund, warum Microsoft diese Überladungen von 'Func' nicht hinzufügen konnte. –

Verwandte Themen