27

Considering the following code:

public void CacheData()
{
    Task.Run((Action)CacheExternalData);
    Task.Run(() => CacheExternalData());

    Task.Run(CacheExternalDataTask);

    Task.Run(CacheExternalData);
}

public Task CacheExternalDataTask()
{
    // Long running code
    return Task.FromResult("Data");
}

public void CacheExternalData()
{
    // Long running code
}

Why is Task.Run(CacheExternalData) ambiguous? And Task.Run(CacheExternalDataTask) is not?

When calling Task.Run with CacheExternalData I would have thought it was clear to the compiler that the method does not return a Task and it should resolve to an Action?

Boann
  • 48,794
  • 16
  • 117
  • 146
Tom Bowen
  • 8,214
  • 4
  • 22
  • 42

1 Answers1

30

It should be clear, but the language specification never said that mismatched return types would have any effect during overload resolution. Because of that, there was no rule that said to prefer Action over Func<Task>. If Action would be picked, sure, it would work. If Func<Task> would be picked, then sure, you'd get an error. But to pick either, overload resolution has to succeed, and it isn't taking this into account.

This is supposed to be fixed with new overload resolution in C# 7.3.