Simcha Khabinsky
Simcha Khabinsky

Reputation: 2039

C# Func Parameter Overloads - Ambiguous

I have two functions that take in different Func parameters. The compiler is telling me it can't differentiate between these functions.

1)

public static async Task<TResult> SomeMethodName<TSource, TResult>
(Func<TSource, Task<TResult[]>> FunctionToRun)

2)

public static async Task<TResult> SomeMethodName<TSource, TResult>
(Func<TSource, Task<TResult>> FunctionToRun)

The difference is slight - but it seems that the C# compiler is not picking it up and can't tell the difference.

Is there a reason why Func<...> type parameters' don't get checked?


Edit - Adding User Method Call Code:

Error is on this line:

var data = await SomeMethodName<model, model2>(someModel, SomeOtherMethod);

SomeOtherMethod method:

public static Task<model2[]> SomeOtherMethod(model model)
{
    Task<model2[]> data = SomeThirdMethodThatReturnsTasks(model);
    return data;
}

Error Details:

The call is ambiguous between the following methods or properties: 
SomeMethodName<model,model2>(model,System.Func<model,System.Threading.Tasks.Task<model2[]>>) 
and 
SomeMethodName<model,model2>(model,System.Func<model,System.Threading.Tasks.Task<model2>>)

Upvotes: 0

Views: 438

Answers (2)

Servy
Servy

Reputation: 203839

There is nothing preventing the type of TResult from being an array.

Let's take this example use of the method for a second:

var task = SomeMethodName((int i) => Task.FromResult(new[] { i }));

This code compiles and runs correctly if only the second method is defined. In that case you're calling:

SomeMethodName<int, int[]>(Func<int, Task<int[]>> FunctionToRun)

The cod would also compile and run successfully if you only have the first method defined. then you have:

SomeMethodName<int, int>(Func<int, Task<int[]>> FunctionToRun)

Since generic arguments aren't a part of the signature, these two functions are identical for the purpose of overload resolution. If both of the overloads exist then overload resolution identifies both of them as valid methods, and there is nothing that makes either one of them "better' than the other based on the defined "betterness" criteria. Since it has no way of picking one, it results in a compiler error due to the ambiguity.

Upvotes: 1

Tim S.
Tim S.

Reputation: 56576

The problem isn't with inferring TResult, it's with TSource. When you have a lambda like:

SomeMethodName(x => x.Something);

C# has no idea what x is unless you tell it. Once you specify that, it should be unambiguous to the compiler:

SomeMethodName<string, int>(x => x.Something); // or
SomeMethodName<string, int[]>(x => x.Something);

Upvotes: 0

Related Questions