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事实上是相关的.Run Code Online (Sandbox Code Playgroud)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)所以对于真正的问题,我已经完成了相同的删除示例问题中的第二个构造函数,因为事实证明重载是多余的.
与此同时,我接受了实际上给出问题的潜在解决方案的答案(尽管在原始问题中我忽略了一个明显的答案),尽管它不是我最终使用的.
答案是这样的:
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
| 归档时间: |
|
| 查看次数: |
633 次 |
| 最近记录: |