I would like to write an extension method for a generic type, with additional generic type parameters. I have working code already, but don’t like the result, because the user is required to re-enter the generic type parameters of the existing type.
I have a concrete example, but keep in mind that this is a general problem. I appreciate feedback on the particular problem at hand, but I am looking for general solutions.
For a class of type Action<T>, add an extension method with a signature similar to this:
Func<T, TResult> ToFunc<TResult>();
Here’s my working code:
public static class DelegateExtensions
{
public static Func<T, TResult> ToFunc<T, TResult>(this Action<T> action)
{
return arg => { action(arg); return default(TResult); };
}
}
But the usage stinks:
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<int, float>());
In this example, the int generic parameter is the only value that is acceptable, so it causes unnecessary code duplication.
Type inference does not work here. I think this is because you can’t infer a generic parameter via return type.
This code would solve the problem, but unfortunately does not seem to work:
public static class DelegateExtensions<T>
{
public static Func<T, TResult> ToFunc<TResult>(this Action<T> action)
{
return arg => { action(arg); return default(TResult); };
}
}
Usage would be exactly like you’d expect:
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<float>());
I noticed that System.Linq.Queryable works the way my first chunk of code does, though it usually doesn’t need extra type parameters, so type inference works.
Is there any known trick to get around requiring these duplicate generic type parameters? One thought that comes to mind would be code generators or macros of some sort, but I can’t think of how I’d do it cleanly.
One common trick for this sort of thing is to pass a dummy value of the desired type just for type inference, which is required in certain scenarios involving anonymous types.
How good of a trick this is is up to personal opinion, but this would confuse me every time I called it and every time I came back to a place that I called it. You could also change the semantics of the method to make the second parameter be the return value, allowing the caller to decide if they want the default value or not.
As to your second example, I’m pretty sure extension methods are not allowed on generic types, but I don’t have a link handy