In a similar vein to this question, I decided to see if it was possible to pull out
parameters from a method into implicitly-typed variables without having to define the types. My ideal solution would look something like this:
var result = LiftOutParam((out p1, out p2, out p3) => {
return CallMyMethod(i1, i2, out p1, out p2, out p3);
});
var o1 = result.Item1;
var o2 = result.Item2;
var o3 = result.Item3;
var returnValue = result.Item4;
In this case, CallMyMethod
has 2 normal input variables, 3 out
parameters, and a return value. I want the compiler to automatically determine the types of o1
, o2
, o3
, and returnValue
based on the semantics of the delegate passed into LiftOutParam
. So I created some helper delegates and methods, for each combination of out parameters. Here's an example for 3 out
parameters:
public delegate TReturn Lift<T1, T2, T3, TReturn>(
out T1 o1, out T2 o2, out T3 o3);
public static Tuple<T1, T2, T3, TReturn> LiftOutParam<T1, T2, T3, TReturn>(
Lift<T1, T2, T3, TReturn> Lift) {
T1 o1;
T2 o2;
T3 o3;
TReturn ret = Lift(out o1, out o2, out o3);
return new Tuple<T1, T2, T3, TReturn>(o1, o2, o3, ret);
}
In theory, the compiler should be able to determine the types T1
, T2
, T3
, and TReturn
based on the semantics of the delegate (out p1, out p2, out p3) => { return CallMyMethod(i1, i2, out p1, out p2, out p3); }
. However, the above code doesn't compile unless I specify the types of each of the out
parameters in the delegate.
Is there a way to do what I'm trying to accomplish? To write a generic helper method that can pull the values of out
parameters into implicitly-typed local variables without having to explicitly define the types anywhere?
There are two issues here:
When a ref
or out
modifier is needed for one or more of the parameters of a lambda expression, syntax requires that you must specify the type for all of the parameters of the lambda expression. This is a syntax thing and applies no matter if the compiler would have been able to infer the types or not.
There must be a type to infer. If you have a method
void MyMethod<T>(Action<T> action)
{
}
then you can't call this method like this: MyMethod(t => { });
Because in this case there's no way to infer what T
is. T
must be infered to be one specific type. This could be a type that depends on another generic parameter that is in scope when the MyMethod
is called.