双向隐浇注料类型的重载之间的暧昧电话时,一个派生类型作为参数传递 [英] Ambiguous call between overloads of two-way implicit castable types when a derived type of one is passed as parameter

查看:106
本文介绍了双向隐浇注料类型的重载之间的暧昧电话时,一个派生类型作为参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(试图找到凝聚了问题,可以是一个非常艰巨的任务,一个标题!)



我对此产生调用一些重载方法下面的类歧义编译器错误:

 公共类MyClass的
{
公共静态无效OverloadedMethod(MyClass的L){}
公共静态无效OverloadedMethod(MyCastableClass L){}

//尝试从下一个隐含的运营商分别评论了这一点。
//注释掉导致违规的测试蒙上()也是如此。
公共静态隐运营商MyCastableClass(MyClass的L)
{
返回新MyCastableClass();
}

//尝试从以前的隐性操作人员分别评论了这一点。
//注释掉导致违规的测试蒙上()也是如此。
公共静态隐运营商MyClass的(MyCastableClass L)
{
返回新MyClass的();
}

静态无效测试()
{
MyDerivedClass衍生=新MyDerivedClass();
MyClass的1级=新MyClass的();
MyClass的类别2 =新MyDerivedClass();
MyClass的3类=新MyCastableClass();
MyCastableClass castableClass1 =新MyCastableClass();
MyCastableClass castableClass2 =新MyClass的();
MyCastableClass castableClass3 =新MyDerivedClass();

OverloadedMethod(衍生); OverloadedMethod(MyClass的L)和OverloadedMethod(MyCastableClass L)
OverloadedMethod(1类)之间的暧昧//调用;
OverloadedMethod(等级2);
OverloadedMethod(3类);
OverloadedMethod(castableClass1);
OverloadedMethod(castableClass2);
OverloadedMethod(castableClass3);

}

公共类MyDerivedClass:MyClass的{}

公共类MyCastableClass {}

有两个非常有趣的事情需要注意:




  1. 注释任何隐含的运营方法消除歧义。

  2. 试图重命名VS第一个方法重载将重命名测试前四()方法调用!



这自然提出了两个问题:




  1. 什么是编译器背后的逻辑错误(即怎么编译器到达歧义)?

  2. 这有什么不对的设计呢?直觉上应该没有模糊和有问题的呼叫应在第一方法重载来解决( OverloadedMethod(MyClass的L,MyClass的R))为 MyDerivedClass 更密切相关的 MyClass的而非浇注料,但不相关的 MyCastableClass 。此外VS重构似乎与这种直觉同意



编辑:
与玩弄后VS重构,我看到VS与在任何代码是定义的第一个过载问题的方法调用相匹配。因此,如果我们交换两个重载VS违规调用一个具有 MyCastableClass 参数相匹配。这些问题仍然是有效的,但。


解决方案

什么是编译器错误背后的逻辑(即如何没有编译器到达歧义)?




首先我们必须确定哪些方法在方法组的。显然,还有方法组中的两种方法。



其次,我们必须确定这两种方法都的适用的。也就是说,每一个参数是隐式转换为相应的参数类型。显然这两种方法都是适用的。



第三,因为有一个以上的应用的方法,一独特最好的方法必须确定。在只有每两个方法只有一个参数的情况下,规则是的的转换的距离的参数的到的参数类型的人们必须的更好的,而不是其他。



有关什么使比另一个更好的转换是在规范中第7.5.3.5规则,这是我在这里引用为了您的方便:




由于转换C1,从类型S转换到类型T1和转换C2从类型S转换到类型T2中,C1是比C2更好的转换如果下列中的至少一个成立:



•从S到存在一个标识转换T1但不从S到T2



•T1是一个更好的转换目标比T2



由于两种不同类型T1和T2,T1比T2更好的转换目标如果下列至少一人持有:



•从T1的隐式转换到T2的存在,并没有隐式转换从T2到T1存在




该规则的目的是确定哪种类型的更具体的的。如果每个香蕉是一种水果,但不是每一个水果是香蕉,然后香蕉比水果更具体。




•T1是一个有符号整数类型和T2是一个无符号整数类型。




运行在列表中向下。是否有一个身份 MyDerivedClass 转换为 MyCastableClass MyClass的?号有没有从 MyClass的的隐式转换为 MyCastableClass ,但不可以的隐式转换会另一种方法?没有。没有理由认为任何一种类型是比其他更具体。要么是整型?无



因此​​没有什么,据以决定那一个比另一个好,因此,这是不明确的。




这有什么不对的设计呢?




这个问题的答案本身。你已经发现的问题之一。




直觉上应该是有没有歧义,并违规呼叫应在第一方法重载的解决MyDerivedClass更密切相关的MyClass的




虽然这可能是直觉给你,规范没有作区分的在此案例的用户定义的转换和任何其他隐式转换之间。不过我注意到,你的distiction的确实的在某些罕见的情况下计算;看到我对细节链接用户定义的转换的文章。 (的http://博客.msdn.com / b / ericlippert /存档/ 2007/04/16 /链式用户自定义,显式转换功能于c.aspx


(Trying to find a title that sums up a problem can be a very daunting task!)

I have the following classes with some overloaded methods that produce a call ambiguity compiler error:

public class MyClass
{
    public static void OverloadedMethod(MyClass l) { }
    public static void OverloadedMethod(MyCastableClass l) { }

    //Try commenting this out separately from the next implicit operator. 
    //Comment out the resulting offending casts in Test() as well.
    public static implicit operator MyCastableClass(MyClass l)
    {
        return new MyCastableClass();
    }

    //Try commenting this out separately from the previous implicit operator.
    //Comment out the resulting offending casts in Test() as well.
    public static implicit operator MyClass(MyCastableClass l)
    {
        return new MyClass();
    }

    static void Test()
    {
        MyDerivedClass derived = new MyDerivedClass();
        MyClass class1 = new MyClass();
        MyClass class2 = new MyDerivedClass();
        MyClass class3 = new MyCastableClass();
        MyCastableClass castableClass1 = new MyCastableClass();
        MyCastableClass castableClass2 = new MyClass();
        MyCastableClass castableClass3 = new MyDerivedClass();

        OverloadedMethod(derived); //Ambiguous call between OverloadedMethod(MyClass l) and OverloadedMethod(MyCastableClass l)
        OverloadedMethod(class1);
        OverloadedMethod(class2);
        OverloadedMethod(class3);
        OverloadedMethod(castableClass1);
        OverloadedMethod(castableClass2);
        OverloadedMethod(castableClass3);

    }

public class MyDerivedClass : MyClass {  }

public class MyCastableClass { }

There are two very interesting things to note:

  1. Commenting out any of the implicit operator methods removes the ambiguity.
  2. Trying to rename the first method overload in VS will rename the first four calls in the Test() method!

This naturally poses two questions:

  1. What it the logic behind the compiler error (i.e. how did the compiler arrive to an ambiguity)?
  2. Is there anything wrong with this design? Intuitively there should be no ambiguity and the offending call should be resolved in the first method overload (OverloadedMethod(MyClass l, MyClass r)) as MyDerivedClass is more closely related to MyClass rather than the castable but otherwise irrelevant MyCastableClass. Furthermore VS refactoring seems to agree with this intuition.

EDIT: After playing around with VS refactoring, I saw that VS matches the offending method call with the first overload that is defined in code whichever that is. So if we interchange the two overloads VS matches the offending call to the one with the MyCastableClass parameter. The questions are still valid though.

解决方案

What it the logic behind the compiler error (i.e. how did the compiler arrive to an ambiguity)?

First we must determine what methods are in the method group. Clearly there are two methods in the method group.

Second, we must determine which of those two methods are applicable. That is, every argument is convertible implicitly to the corresponding parameter type. Clearly both methods are applicable.

Third, given that there is more than one applicable method, a unique best method must be determined. In the case where there are only two methods each with only one parameter, the rule is that the conversion from the argument to the parameter type of one must be better than to the other.

The rules for what makes one conversion better than another is in section 7.5.3.5 of the specification, which I quote here for your convenience:

Given a conversion C1 that converts from a type S to a type T1, and a conversion C2 that converts from a type S to a type T2, C1 is a better conversion than C2 if at least one of the following holds:

• An identity conversion exists from S to T1 but not from S to T2

• T1 is a better conversion target than T2

Given two different types T1 and T2, T1 is a better conversion target than T2 if at least one of the following holds:

• An implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists

The purpose of this rule is to determine which type is more specific. If every Banana is a Fruit but not every Fruit is a Banana, then Banana is more specific than Fruit.

• T1 is a signed integral type and T2 is an unsigned integral type.

Run down the list. Is there an identity conversion from MyDerivedClass to either MyCastableClass or MyClass? No. Is there an implicit conversion from MyClass to MyCastableClass but not an implicit conversion going the other way? No. There is no reason to suppose that either type is more specific than the other. Are either integral types? No.

Therefore there is nothing upon which to base the decision that one is better than the other, and therefore this is ambiguous.

Is there anything wrong with this design?

The question answers itself. You've found one of the problems.

Intuitively there should be no ambiguity and the offending call should be resolved in the first method overload as MyDerivedClass is more closely related to MyClass

Though that might be intuitive to you, the spec does not make a distinction in this case between a user-defined conversion and any other implicit conversion. However I note that your distiction does count in some rare cases; see my article on chained user-defined conversions for details. (http://blogs.msdn.com/b/ericlippert/archive/2007/04/16/chained-user-defined-explicit-conversions-in-c.aspx)

这篇关于双向隐浇注料类型的重载之间的暧昧电话时,一个派生类型作为参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆