在C#中,隐式转换的顺序是什么?

9
当x是用户定义的类的对象时,在Console.WriteLine(x)中进行的隐式转换顺序是什么?
    class Vector
    {
        public int x = 12;       

        public static implicit operator double(Vector v1)
        {
            return 3.14;
        }

        public static implicit operator int(Vector v1)
        {
            return 42;
        }

        public override string ToString()
        {
            return this.x.ToString();
        }

    }

    static void Main(string[] args)
    {
        Vector v11 = new Vector();
        Console.WriteLine(v11);
    }

为什么我得到的是42,而不是3.14或“12”?为什么我不能添加一个额外的隐式转换到字符串/在CW(int)和CW(string)之间存在歧义,导致编译器错误/:
        public static implicit operator string(Vector v1)
        {
            return "42";
        }

我知道应该避免使用隐式转换,但只是出于好奇!


2
不,它会打印出42(在Visual Studio 2017社区版的新安装中)。 - Matija Lokar
2
我假设它返回42是因为v11.x是一个int,而不是doublestring,当在Console.WriteLine()中使用v11时,它调用了VectorToString()方法,该方法又调用了v11.x.ToString()。如果我错了,请纠正我。 - absoluteAquarian
2
C#中的重载决策是规范中最有趣的部分!当我说“有趣”时,我的意思是“当你深入研究时非常复杂,希望它能做你想要的事情,这样你就不必深入细节”。接受int参数的Console.WriteLine重载被认为是“更好”的选择,对于一个非常具体的“更好”解释。我还没有研究过确切的细节。如果Eric Lippert有时间,他会出现并解释的 :-) - Jeroen Mostert
5
这引起了我的好奇心,于是我去找到了“隐式操作符是否比ToString()方法优先级更高?”- 答案是肯定的。 - stuartd
2
在这种情况下,.ToString 的存在或缺失是一个转移注意力的问题,因为它从未参与其中:这需要选择 Console.WriteLine(object) 重载以便可以在后台调用 .ToString()。只有通过显式强制转换才能实现这一点,因为如果有选择的话,object 永远不是更好的目标。 - Jeroen Mostert
显示剩余7条评论
1个回答

4
因此,所打印的内容完全取决于选择哪个 Console.WriteLine 的重载。选择哪个重载基于规范中关于函数成员“优越性”的第7.5.3.2节。
当一个参数比另一个参数“更具体”时,一个重载比另一个重载“更好”。 “更具体”意味着从更具体类型到不太具体的类型有隐式转换,而从不太具体的类型到更具体的类型没有隐式转换。 object 是最不具体的重载,因为它不能隐式转换为 int、double 或 string,但每种类型都可以隐式转换为它。int 比 double 更具体,因为从 int 到 double 有一个隐式转换,但是从 double 到 int 没有转换。int 和 string 之间没有隐式转换,因此两者都不是更具体的,因此也不比另一个更好或更差。
因此,如果有一个从对象到 string 的隐式转换,则会考虑字符串重载,并且存在“最佳”重载的平局,您将收到错误信息。当缺少它时,所有被考虑的重载中有一个“最具体”类型(即int),因此它是“最好的”,并且选择该重载。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接