Let's have the following code (type-safe stubs for jQuery):
public interface IjQueryPromise { }
public interface IjQueryPromise<TResult> : IjQueryPromise { }
public static class jQueryPromiseEx
{
public static T Done<T>(this T t, params Action[] doneCallbacks)
where T : IjQueryPromise { return t; }
public static T Done<T, TResult>(this T t, params Action<TResult>[] doneCallbacks)
where T : IjQueryPromise<TResult> { return t; }
}
Using this code, I am trying to allow calling:
Done()
with callback without arguments either on IjQueryPromise
or IjQueryPromise<TResult>
Done()
with callback with one argument of type TResult
on IjQueryPromise<TResult>
.But since C# (v5.0) is unable to overload on generic constraints, passing lambda like:
(r) => DoSomething(r)
will produce compiler error:
Delegate 'System.Action' does not take 1 arguments.
I am implementing the methods as extension methods to return the type of the object on which the function is called.
The only idea what I have is automatically inline the code inside the interfaces and all their implementations.
Is it possible solve this in C# some better way?
Or does already exist a tool that do the inlining?
EDIT: I am designing the API for developers. I know that I can cast to delegate, but I do not want the developers (users of the API) to be forced to do the cast every time.
This isn't an issue with overload resolution.
It has nothing to do with a conflict with the other overload.
This is an issue with type inference. Your second overload won't be able to infer the type of TResult
if you don't indicate the type of the parameter for the lambda, or the type of the entire delegate.
This is easy enough to see by simply removing the first overload from your application entirely. All that will do is change the error message from what you're getting to one saying that type inference has failed.
One way that you can both allow type inference and actually not provide any of the type information elsewhere (i.e typing the type out for the lambda parameter) would be to go down to just one generic argument:
public static IjQueryPromise<T> Done<T>(this IjQueryPromise<T> t,
params Action<T>[] doneCallbacks)
{ return t; }