我的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)
基本上,运算符重载解析不包括隐式用户定义的转换,以便找到可能适用的运算符。
\n来自 C# 5 规范第 7.3.4 节:
\n\n\n形式的操作
\nx op y(其中op是可重载二元运算符,x是类型 的表达式X,并且y是类型 的表达式Y)按如下方式处理:\n
\n- 确定由运算运算符提供
\nX并Y为运算运算符提供的候选用户定义运算符的集合。op(x, y)该集合由 X 提供的候选运算符和 提供的候选运算符的并集组成Y,每个运算符均使用 \xc2\xa77.3.5 的规则确定。如果X和Y是相同类型,或者如果X和Y派生自公共基类型,则共享候选运算符仅在组合集中出现一次。
并且 7.3.5 在搜索一组运算符时不包括隐式用户定义的转换。
\nTerm请注意,如果在类中声明了隐式转换,这也不起作用Variable- 尽管指定和实现会更合理,因为编译器可以查看从操作数类型到其他类型的转换集,并使用那些用于过载解析。
不过,这只是从寻找运营商入手的问题。当编译器考虑重载是否适用时,它很乐意执行隐式转换。例如,在您的情况下,如果您添加:
\nclass A\n{\n public static B operator *(A a, B b) { return new B(); }\n}\nRun Code Online (Sandbox Code Playgroud)\n那么这是有效的:
\nA a = new A(); \nConsole.WriteLine(a * a);\nRun Code Online (Sandbox Code Playgroud)\n