错误的重载导致编译器错误

Ste*_*eve 9 c# lambda member-functions overload-resolution

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

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

为了避免因误解类继承如何工作而引起的类似问题的混淆,我在这个例子中故意避免任何继承.

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

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

错误CS0121:以下方法或属性之间的调用不明确:'WorkerAorB.WorkerAorB(System.Func <A>)'和'WorkerAorB.WorkerAorB(System.Func <B>)'

WorkerAandB 给

错误CS0407:'ManagerA.GetA()'的返回类型错误

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

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) { }
}
Run Code Online (Sandbox Code Playgroud)
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!
Run Code Online (Sandbox Code Playgroud)

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

更新:我从示例中省略了一些信息.在真正的问题中,类A和B事实上是相关的.

class B : A { }
Run Code Online (Sandbox Code Playgroud)

此外,在进一步反映真正的问题,呼吁

public WorkerAandB(Func<B> funcB) { }
Run Code Online (Sandbox Code Playgroud)

喜欢

    new WorkerAandB(GetB)
Run Code Online (Sandbox Code Playgroud)

实际上相当于

    new WorkerAandB(GetB, GetB)
Run Code Online (Sandbox Code Playgroud)

所以对于真正的问题,我已经完成了相同的删除示例问题中的第二个构造函数,因为事实证明重载是多余的.

与此同时,我接受了实际上给出问题的潜在解决方案的答案(尽管在原始问题中我忽略了一个明显的答案),尽管它不是我最终使用的.

Sid*_*r94 1

答案是这样的:

    public 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((Func<A>)GetA); // cast to avoid error CS0121
        new WorkerAorB((Func<A>)GetAstatic); // cast to avoid error CS0121
        new WorkerAorB(() => GetA()); // ok
        new WorkerAorB(GetAfunc); // ok

        new WorkerAandB(() => new A()); // ok
        new WorkerAandB((Func<A>)GetA); // cast to avoid error CS0407
        new WorkerAandB((Func<A>)GetAstatic); // cast to avoid error CS0407
        new WorkerAandB(GetA, null); // ok
        new WorkerAandB(GetAstatic, null); // ok
        new WorkerAandB(GetAfunc); // ok
    }
Run Code Online (Sandbox Code Playgroud)

至于为什么它在没有强制转换的情况下不起作用......似乎对于编译器来说 GetA 不是来自类型,Func<A>而只是一个method group