运算符重载 - 为什么要静态解析?

5

为什么要静态解析重载运算符?这对我来说似乎是一种奇怪的选择——我能想到的唯一优点是获得一些小的性能提升(但JIT有时也可以避免这个问题),代价是产生一些相当不直观的行为,也就是说,基本上我必须将运算符转发到虚函数才能获得所需的行为。

这只是从C++中继承过来的吗?还是还有其他很好的理由?


4
"Design decision" .. now, where is Eric? ;-) 这句话的意思是“设计决策……现在Eric在哪里?”;-) 是一种调侃和询问Eric位置的方式。Another somewhat related question is "why aren't methods virtual by default"? 另一个有关的问题是“为什么方法不默认为虚函数”? - user166390
3
他在这里:http://blogs.msdn.com/b/ericlippert/archive/2007/05/14/why-are-overloaded-operators-always-static-in-c.aspx - Hans Passant
3个回答

3

请查看Eric Lippert的文章为什么C#中的重载运算符总是静态的?

相反,当面临潜在的语言特性时,我们应该问自己的问题是“这个功能的吸引人的好处是否值得所有成本?” 成本远不止设计、开发、测试、文档编写和维护一个功能的平凡货币成本。还有更微妙的成本,例如,这个功能会使将来更改类型推断算法更加困难吗?这是否会让我们进入一个无法在不引入向后兼容性破坏的情况下进行更改的世界?等等。

在这种特定情况下,吸引人的好处很小。如果您想在C#中拥有虚拟分派重载运算符,可以非常轻松地使用静态部件构建它。 [...]

支持基于实例的运算符是可能的,但C#语言设计者认为与使其正常工作所需的努力相比,收益不大。


1
我发誓Eric在他所有与C#设计相关的文章中都复制粘贴了那个第一段 :-) - user166390
这位权威人士提供的链接很好,他关于一些可能存在的问题是正确的(不过解决方案还是相当简单的 - 只是没有我想要的那么优雅)。 - Voo

2
考虑重载引用类型运算符的情况。它可以在运算符的任一侧为空。
如果运算符是实例方法,它们将无法正常工作。

2
但是Scala允许在引用类型上进行“运算符重载”:在解析后,x * yx.multiply(y)没有任何区别。 - user166390
只是提出一个反驳的观点 :) 另外,我在这里遇到了 Nullable 类型的问题,不知道它们在所有这些中的适用性: (int)?10 > (int?)null ... 最终有意义,但仍然让我感到有些痛苦 :( - user166390
是的,显然你至少需要指定参数如何被评估(尽管x op y被解释为x.op(y)似乎是合乎逻辑的选择)。我可以理解那里的不对称之处的争论。 - Voo

2

我脑海中浮现出两件事,其中任何一件都可以独立地打破交易:

  1. 哪些运算符?二元运算符有两个操作数,并且基于两个参数类型的动态分派不可用!“经典”的virtual方法仅基于this的运行时类型进行分派。
  2. 什么是能够证明额外复杂性的使用案例?

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