假设我在 C# 中有一个复数类,其加法运算符定义如下。
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
并像这样使用。
Complex c1, c2, c3, c4;
c1 = new Complex(...)
...
c4 = new Complex(...)
Complex csum = c1 + c2 + c3 + c4;
现在,我的问题是 C# 编译器+运行时将如何处理这个问题。显然,它看起来会做这样的事情。
ct1 = c1 + c2; // ct1 is a temporary object created by the compiler
ct2 = ct1 + c3;
csum = ct2 + c4;
或者它是否足够聪明,意识到它可以像这样以更好的方式(更少创建新的临时对象)做到这一点。
ct = c1 + c2;
ct += c3;
csum = ct + c4;
最佳答案
除了为它命名的局部变量外,单个表达式等效于(就生成的代码而言)单独的语句。 JIT 可以优化它,但编译器不能。请注意,如果 Complex
是一个值类型,那么它实际上不会涉及分配对象1。
值得注意的是,+
运算符在C#中专门为string
处理(由语言指定,不在框架本身)正是为了避免这种情况事情:x + y + z
被(或至少可以)转换为 string.Concat(x, y, z)
以避免创建临时字符串。
1 我所说的“对象”指的是一 block 内存区域,带有对象 header (类型引用、同步块(synchronized block)等),后跟字段,分配在堆上,而不是“值类型” value”,它只包含数据本身,可能在堆上,也可能在栈上。堆栈/堆部分是 implementation detail当然,但是一个潜在的重要的...我相信区分“只是一个值类型值”和“一个完整的对象”是合理的。
关于c# - C#如何处理运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9500754/