时间:2019-03-17 标签:c#generic重载方法dispatchingambiguously

发布于 2024-09-02 06:15:20 字数 645 浏览 5 评论 0原文

我刚刚遇到了一种情况,方法分派不明确,想知道是否有人可以解释编译器(.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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

静谧 2024-09-09 06:15:20

它遵循 C# 4 规范(“更好的功能成员”)。

首先(嗯,在看到这两种方法都适用之后)我们需要检查从参数类型到参数类型的转换。在本例中,它相当简单,因为只有一个参数。参数类型到参数类型的转换都不是“更好”,因为两者都是从 ConcreteA 转换为 IfaceA。因此,它转向下一组标准,包括:

否则,如果 MP 有更具体的
参数类型不是MQ,那么MP就是
比MQ好。令 {R1, R2, …, RN}
和 {S1, S2, …, SN} 代表
未实例化和未扩展
MP和MQ的参数类型。议员们
参数类型比更具体
MQ 的 if,对于每个参数,RX 不是
不如 SX 具体,并且,对于 at
至少一个参数,RX 多一个
比SX具体:比SX具体:

  • 类型参数不如非类型参数具体。
  • ...

因此,即使转换同样好,直接使用IfaceA(而不是通过委托)的重载被认为“更好”,因为类型的参数IfaceAT 类型的参数更具体。

没有办法让编译器警告这种行为——这只是正常的重载解析。

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 to IfaceA. It therefore moves on to the next set of criteria, including this:

Otherwise, if MP has more specific
parameter types than MQ, then MP is
better than MQ. Let {R1, R2, …, RN}
and {S1, S2, …, SN} represent the
uninstantiated and unexpanded
parameter types of MP and MQ. MP’s
parameter types are more specific than
MQ’s if, for each parameter, RX is not
less specific than SX, and, for at
least one parameter, RX is more
specific than SX:specific than SX:

  • A type parameter is less specific than a non-type parameter.
  • ...

So even though the conversion is equally good, the overload using IfaceA directly (rather than via delegates) is deemed "better" because a parameter of type IfaceA is more specific than a parameter of type T.

There's no way of getting the compiler to warn on this behaviour - it's just normal overload resolution.

恏ㄋ傷疤忘ㄋ疼 2024-09-09 06:15:20

因为编译器首先选择最具体的。

如果你像这样调用会发生什么:

void code()   
{ 
    var concreteB = new ConcreteB(); 

    IfaceA  x = concreteB.Add(new ConcreteA()); 
} 

Because the compiler chooses the most specific first.

What happens if you call like so:

void code()   
{ 
    var concreteB = new ConcreteB(); 

    IfaceA  x = concreteB.Add(new ConcreteA()); 
} 
风吹雨成花 2024-09-09 06:15:20

这有点让我想起 Jon Skeet 的 BrainTeaser
如果您不想信任编译器,您可能需要通过调用 Add(new ConcreteA()) 来强制其选择

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())

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文