blu
blu

Reputation: 13175

Func<T> with out parameter

Can I pass a method with an out parameter as a Func?

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

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

Func needs a type so out won't compile there, and calling listFunction requires an int and won't allow an out in.

Is there a way to do this?

Upvotes: 210

Views: 71715

Answers (4)

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422026

ref and out are not part of the type parameter definition so you can't use the built-in Func delegate to pass ref and out arguments. Of course, you can declare your own delegate if you want:

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

Upvotes: 265

nawfal
nawfal

Reputation: 73183

The Func family of delegates (or Action for that matter) are nothing but simple delegate types declared like

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

etc. Delegates as such can have out/ref parameters, so in your case its only a matter of custom implementation by yourself as other answers have pointed out. As to why Microsoft did not pack this by default, think of the sheer number of combinations it would require.

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)

for just two parameters. We have not even touched ref. It would actually be cumbersome and confusing for developers.

Upvotes: 18

Logan Capaldo
Logan Capaldo

Reputation: 40336

You could wrap it in a lambda/delegate/function/method that exposed the right interface and called FindForBar, but I suspect that FindForBar has count as an out parameter as a reason, so you'd need to be sure throwing that information away was ok/safe/desirable/had the right results (you'd need to be sure of this even if you could just directly pass in FindForBar).

Upvotes: 0

ChaosPandion
ChaosPandion

Reputation: 78272

Why not create a class to encapsulate the results?

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

Upvotes: 28

Related Questions