用户定义的重载运算符参数的隐式转换

Alw*_*ing 5 c#

我的Term类中定义了以下运算符重载:

public static Term operator *(int c, Term t) {...}
Run Code Online (Sandbox Code Playgroud)

该类还定义了从a Variable到的隐式转换Term:

public static implicit operator Term(Variable var) {...}
Run Code Online (Sandbox Code Playgroud)

我想了解为什么以下不编译:

static void Main(string[] args)
{
    Variable var = ...; // the details don't matter
    Console.WriteLine(2 * var); // var isn't implicitly converted to Term...
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

编译器说:

运算符'*'不能应用于'int'和'OOSnake.Variable'类型的操作数

为什么不operator *发现我的超负荷?

编辑:根据评论中的建议,这是一个重新产生错误的小完整示例:

namespace Temp
{
    class A { 
    }
    class B
    {
        public static implicit operator B(A a) { return new B(); }
        public static B operator *(int c, B b) { return new B(); }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(2 * new A());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 4

基本上,运算符重载解析不包括隐式用户定义的转换,以便找到可能适用的运算符。

\n

来自 C# 5 规范第 7.3.4 节:

\n
\n

形式的操作x op y(其中op是可重载二元运算符,x是类型 的表达式X,并且y是类型 的表达式Y)按如下方式处理:

\n
    \n
  • 确定由运算运算符提供XY为运算运算符提供的候选用户定义运算符的集合。op(x, y)该集合由 X 提供的候选运算符和 提供的候选运算符的并集组成Y,每个运算符均使用 \xc2\xa77.3.5 的规则确定。如果XY是相同类型,或者如果XY派生自公共基类型,则共享候选运算符仅在组合集中出现一次。
  • \n
\n
\n

并且 7.3.5 在搜索一组运算符时不包括隐式用户定义的转换。

\n

Term请注意,如果在类中声明了隐式转换,这也不起作用Variable- 尽管指定和实现会更合理,因为编译器可以查看从操作数类型到其他类型的转换集,并使用那些用于过载解析。

\n

不过,这只是从寻找运营商入手的问题。当编译器考虑重载是否适用时,它很乐意执行隐式转换例如,在您的情况下,如果您添加:

\n
class A\n{\n    public static B operator *(A a, B b) { return new B(); }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

那么这是有效的:

\n
A a = new A();        \nConsole.WriteLine(a * a);\n
Run Code Online (Sandbox Code Playgroud)\n