Неоднозначность с действием и параметром Func

Как возможно, что этот код

TaskManager.RunSynchronously<MyObject>(fileMananager.BackupItems, package);

вызывает ошибку компиляции

The call is ambiguous between the following methods or properties:
'TaskManager.RunSynchronously<MyObject>(System.Action<MyObject>, MyObject)' and
'TaskManager.RunSynchronously<MyObject>(System.Func<MyObject, bool>, MyObject)'

когда подпись действия

public void BackupItems(MyObject package)

и "неоднозначные" методы

static class TaskManager
{
    public static void RunSynchronously<TInput>(Action<TInput> task, TInput param)
    {
        Task.Factory.StartNew(() => task(param));
    }

    public static bool RunSynchronously<TInput>(Func<TInput, bool> task, TInput param)
    {
        return Task.Factory.StartNew(() => task(param)).Result;
    }
}

Мне кажется, что между этими методами существует большая разница. Что мне здесь не хватает?

EDIT:

Помимо принятого ответа, я просто встретил решение по аналогичному вопросу. Вот ссылка .

Ответы

Ответ 1

Причина в том, что возвращаемый тип метода не является частью его подписи. Таким образом, при разрешении правильной перегрузки компилятор только смотрит на параметр метода.

Самое простое решение - просто не использовать преобразование группы неявных методов. Все следующие компиляции:

TaskManager.RunSynchronously<MyObject>(
    x => fileMananager.BackupItems(x), package);

TaskManager.RunSynchronously<MyObject>(
    (Action<MyObject>)fileMananager.BackupItems, package);

TaskManager.RunSynchronously<MyObject>(
    new Action<MyObject>(fileMananager.BackupItems), package);

Первый из них является самым изящным из них, но он также является единственным, у которого есть незначительное влияние производительности во время выполнения, из-за дополнительного перенаправления. Однако это воздействие настолько мало, что вам на самом деле все равно.

Ответ 2

Я столкнулся с той же проблемой, решение было:

var r = RunSynchronously<bool>(x =>
{
    return true;
}, true);

RunSynchronously<bool>(x =>
{
}, true);

Теперь, почему компилятор не может этого сделать?

Ответ 3

Другое возможное объяснение этому в настоящее время заключается в следующем:

Код был написан для С# версии 7.3 (по умолчанию используется MSBuild 16.x, что соответствует VS2019), но попытка сборки осуществляется с более ранней версией С# (которая по умолчанию для MSBuild 15.x, что соответствует VS2017).

Более ранние версии С# выдают эту ошибку, но перегрузка корректно разрешается в С# 7.3.