使用 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!
可以GetA
或 GetAstatic
以某种方式修改函数以帮助编译器识别要使用的正确重载,或者在此上下文中只允许使用 lambda 和/或显式声明的委托(delegate)?
Update: Some information that I'd omitted from the example. In the real problem, classes
A
andB
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/