c# - 错误的重载导致编译器错误

标签 c# lambda overload-resolution member-functions

使用 VS2013,在下面的示例中,当尝试将函数传递给 worker 的构造函数时会给出两个不同的错误,但是,具有相同原型(prototype)的 lambda 函数是可以的。

我做错了什么,我该如何更改 GetA 的定义?允许它被传递的函数?

为了避免因误解类继承的工作原理而与听起来相似的问题混淆,我在这个例子中有意避免了任何继承。

WorkerA只能接受一个Func<A>在它的构造函数中。 WorkerAorB更灵活,可以接受 Func<A>Func<B> . WorkerAandB是最有能力的,可以接受 Func<A>和一个 Func<B>同时(或两者之一)。这是最接近我真实代码的。

但是,当管理器中的代码尝试实例化 worker 时,WorkerA按预期工作,但是 WorkerAorB给出错误:

error CS0121: The call is ambiguous between the following methods or properties: 'WorkerAorB.WorkerAorB(System.Func<A>)' and 'WorkerAorB.WorkerAorB(System.Func<B>)'

WorkerAandB

error CS0407: 'A ManagerA.GetA()' has the wrong return type

在每种情况下,似乎编译器都无法确定在将引用传递给实际函数而不是 lambda 或现有的 Func<A> 时使用哪个重载。变量,并在 WorkerAandB如果它明确选择了错误的重载,并给出了有关传递函数的返回类型的错误。

class A { }
class B { }

class WorkerA
{
  public WorkerA(Func<A> funcA) { }
}

class WorkerAorB
{
  public WorkerAorB(Func<A> funcA) { }
  public WorkerAorB(Func<B> funcB) { }
}

class WorkerAandB
{
  public WorkerAandB(Func<A> funcA, Func<B> funcB = null) { }
  public WorkerAandB(Func<B> funcB) { }
}
class ManagerA
{
  A GetA() { return new A(); }
  static A GetAstatic() { return new A(); }
  Func<A> GetAfunc = GetAstatic;

  ManagerA()
  {
    new WorkerA(() => new A()); // ok
    new WorkerA(GetA); // ok
    new WorkerA(GetAstatic); // ok

    new WorkerAorB(() => new A()); // ok
    new WorkerAorB(() => new B()); // ok
    new WorkerAorB(GetA); // error CS0121
    new WorkerAorB(GetAstatic); // error CS0121
    new WorkerAorB(() => GetA()); // ok
    new WorkerAorB(GetAfunc); // ok

    new WorkerAandB(() => new A()); // ok
    new WorkerAandB(GetA); // error CS0407
    new WorkerAandB(GetAstatic); // error CS0407
    new WorkerAandB(GetA, null); // ok
    new WorkerAandB(GetAstatic, null); // ok
    new WorkerAandB(GetAfunc); // ok
  }
}

// class ManagerB or ManagerAandB left as an exercise to the reader!

可以GetAGetAstatic以某种方式修改函数以帮助编译器识别要使用的正确重载,或者在此上下文中只允许使用 lambda 和/或显式声明的委托(delegate)?

Update: Some information that I'd omitted from the example. In the real problem, classes A and B are in fact related.

class B : A { }

Also, on further reflection of the real problem, a call to

public WorkerAandB(Func<B> funcB) { }

like

    new WorkerAandB(GetB)

was in fact equivalent to

    new WorkerAandB(GetB, GetB)

So for the real problem, I've done the equivalent of deleting the second constructor in the example problem, as it turns out the overload was redundant.

In the meantime I've accepted the answer that actually gave a potential solution to the problem (albeit an obvious one that I'd omitted to mention in the original question), even though it wasn't what I eventually used.

最佳答案

Eric Lippert 回答的关键部分 here ,因为它适用于这个问题,似乎是“开销解决方案不考虑返回类型”。因此,如果您通过将每个 Func 替换为 Action 来重写您的示例,错误就会消失,因为现在有非空参数列表来解决歧义。

class A { }
class B { }

class WorkerA
{
    public WorkerA(Action<A> doA) { }
}

class WorkerAorB
{
    public WorkerAorB(Action<A> doA) { }
    public WorkerAorB(Action<B> doB) { }
}

class WorkerAandB
{
    public WorkerAandB(Action<A> doA, Action<B> doB = null) { }
    public WorkerAandB(Action<B> doB) { }
}
class ManagerA
{
    void DoA(A a) { }
    static void DoAstatic(A a) { }
    Action<A> DoAfunc = DoAstatic;

    ManagerA()
    {
        new WorkerA((A a) => { }); // ok
        new WorkerA(DoA); // ok
        new WorkerA(DoAstatic); // ok

        new WorkerAorB((A a) => { }); // ok
        new WorkerAorB((B b) => { }); // ok
        new WorkerAorB(DoA); // ok
        new WorkerAorB(DoAstatic); // ok
        new WorkerAorB(a => { }); // ok
        new WorkerAorB(DoAfunc); // ok

        new WorkerAandB(a => { }); // ok
        new WorkerAandB(DoA); // ok
        new WorkerAandB(DoAstatic); // ok
        new WorkerAandB(DoA, null); // ok
        new WorkerAandB(DoAstatic, null); // ok
        new WorkerAandB(DoAfunc); // ok
    }
}

关于c# - 错误的重载导致编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29706054/

相关文章:

c# - DotNetOpenAuth.Messaging - 协议(protocol)错误 : This message has a timestamp of {0}, 超出了 future 允许的时钟偏差

c# - HttpServerUtility.UrlTokenDecode 似乎只返回 null

Java 8 从 Map 中的匹配值中提取第一个键

c++ - 包含模板参数包的函数模板的部分排序

c++ - 用双花括号初始化 vector :std::string vs int

c# - ServiceStack Redis如何实现分页

c# - 如何获取 IDispatchMessageInspector 中的异常对象?

python - 如何使用 lambda 搜索多个单词

C#-根据与另一个列表的部分交集从列表中选择特定项目 (Linq + Lambda)

c# - 重载的方法组参数会混淆重载的解析?