时间:2019-03-17 标签:c#generic重载方法dispatchingambiguously
我刚刚遇到了一种情况,方法分派不明确,想知道是否有人可以解释编译器(.NET 4.0.30319)在什么基础上选择调用什么重载
interface IfaceA
{
}
interface IfaceB<T>
{
void Add(IfaceA a);
T Add(T t);
}
class ConcreteA : IfaceA
{
}
class abstract BaseClassB<T> : IfaceB<T>
{
public virtual T Add(T t) { ... }
public virtual void Add(IfaceA a) { ... }
}
class ConcreteB : BaseClassB<IfaceA>
{
// does not override one of the relevant methods
}
void code()
{
var concreteB = new ConcreteB();
// it will call void Add(IfaceA a)
concreteB.Add(new ConcreteA());
}
无论如何,为什么编译器不警告我,甚至为什么它不警告我编译? 非常感谢您的任何答复。
I just hit a situation where a method dispatch was ambiguous and wondered if anyone could explain on what basis the compiler (.NET 4.0.30319) chooses what overload to call
interface IfaceA
{
}
interface IfaceB<T>
{
void Add(IfaceA a);
T Add(T t);
}
class ConcreteA : IfaceA
{
}
class abstract BaseClassB<T> : IfaceB<T>
{
public virtual T Add(T t) { ... }
public virtual void Add(IfaceA a) { ... }
}
class ConcreteB : BaseClassB<IfaceA>
{
// does not override one of the relevant methods
}
void code()
{
var concreteB = new ConcreteB();
// it will call void Add(IfaceA a)
concreteB.Add(new ConcreteA());
}
In any case, why does the compiler not warn me or even why does it compile?
Thank you very much for any answers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
它遵循 C# 4 规范(“更好的功能成员”)。
首先(嗯,在看到这两种方法都适用之后)我们需要检查从参数类型到参数类型的转换。在本例中,它相当简单,因为只有一个参数。参数类型到参数类型的转换都不是“更好”,因为两者都是从
ConcreteA
转换为IfaceA
。因此,它转向下一组标准,包括:因此,即使转换同样好,直接使用
IfaceA
(而不是通过委托)的重载被认为“更好”,因为类型的参数IfaceA
比T
类型的参数更具体。没有办法让编译器警告这种行为——这只是正常的重载解析。
It follows the rules in section 7.5.3.2 of the C# 4 specification ("Better function member").
First (well, after seeing that both methods are applicable) we need to check the conversions from argument types to parameter types. In this case it's reasonably simple because there's only one argument. Neither conversion of argument type to parameter type is "better" because both are converting from
ConcreteA
toIfaceA
. It therefore moves on to the next set of criteria, including this:So even though the conversion is equally good, the overload using
IfaceA
directly (rather than via delegates) is deemed "better" because a parameter of typeIfaceA
is more specific than a parameter of typeT
.There's no way of getting the compiler to warn on this behaviour - it's just normal overload resolution.
因为编译器首先选择最具体的。
如果你像这样调用会发生什么:
Because the compiler chooses the most specific first.
What happens if you call like so:
这有点让我想起 Jon Skeet 的 BrainTeaser。(new ConcreteA()) 来强制其选择
如果您不想信任编译器,您可能需要通过调用 Add
This somewhat reminds me of the "Type inference a-go-go" in Jon Skeet's BrainTeaser.
If you do not want to trust the compiler, you might want to force its choice by calling
Add<ConcreteA>(new ConcreteA())