【问题标题】:Ambiguity with Action and Func parameterAction 和 Func 参数的歧义
【发布时间】:2013-09-10 10:04:46
【问题描述】:

这段代码怎么可能

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;
    }
}

在我看来,这些方法之间存在很大差异。我在这里错过了什么?

编辑:

除了接受的答案之外,我刚刚在类似问题中遇到了一个解决方案。这是link

【问题讨论】:

标签: c# delegates task-parallel-library ambiguity


【解决方案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);

第一个是其中最优雅的,但它也是唯一一个对运行时性能有轻微影响的,因为额外的重定向。但是,这种影响是如此之小,以至于您实际上不应该在意。

【讨论】:

  • 这是对所有方法有效还是仅对 lambda 有效?
  • @AlessandroD'Andria:你到底是什么意思?
  • 我没有意识到这一点。有没有办法设计我的 TaskManager.RunSynchronously 方法,这样我就不需要显式转换?
  • @OndrejJanacek:现在,我不知道怎么做,抱歉。
  • @DanielHilgarth 好吧,这不是这个问题的主题。但是,如果您遇到解决方案,请更新您的答案并告诉我。顺便问一下,第一个解决方案中的魔术变量 x 代表什么,package 应该是参数?
【解决方案2】:

现在对此的另一种可能的解释是:

代码是为 C# 版本 7.3 编写的(默认由 MSBuild 16.x 使用,对应于 VS2019),但尝试使用早期版本的 C#(这是 MSBuild 15.x 的默认值,对应于VS2017)。

早期版本的 C# 抛出此错误,但在 C# 7.3 中正确解决了重载问题。

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,解决方法是:

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

    现在,为什么编译器不能这样做???

    【讨论】:

    • 你可以用x =&gt; true代替x =&gt; { return true; }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多