可以得到“;运算符“;后果
本文关键字:后果 运算符 | 更新日期: 2023-09-27 18:27:42
是否可以在C#中获得重载运算符结果的引用,这样就不必使用"new"关键字来创建临时结果(稍后返回)?
下面是我遇到的一个问题的例子:
public class Stats {
public float someField;
public float someOtherField;
public static Stats operator +(Stats a, Stats b) {
Stats c = new Stats(); // I don't want a new one, can I access operators result directly?
c.someField = a.someField + b.someField;
c.someOtherField = a.someOtherField + b.someOtherField;
return c;
}
/*
// This is what I want to achieve, but it would be cooler if static and with the "+"
public Add(SomeType a) {
someField += a.someField;
someOtherField += a.someOtherField
}
*/
}
public class StatObserver {
public Stats statsToObserve;
public Output() {
print(statsToObserve.someField);
}
}
public class Class {
public Stats firstStats = new Stats();
firstStats.someField = 1.5f;
public StatObserver showStats = new StatObserver();
showStats.statsToObserve = firstStats;
public Stats nextStats = new Stats();
nextStats.someField = 3.4f;
// now the tricky part
firstStats += nextStats; // C# handles the += itself correctly
showStats.Output(); // prints "1.5"
// you have to update the observer to get the new value
// it's kind of stupid, because you have to treat firstStats like a value type buts its not
showStats.statsToObserve = firstStats;
showStats.Output(); // prints "4.9"
}
不能直接重载+=
运算符,它被编译为加法和赋值。作为+
运算符的一部分,可以对左侧进行变异,但这将是邪恶的。Add
方法似乎是最干净的设计IMHO。
首先,正如@D.Stanley所指出的,您不能覆盖+=
。您可以覆盖+
,正如您所做的那样,但+
:有一些重要的东西需要实现
数学运算符是非破坏性的,也就是说,它们返回一个结果而不修改操作数
也就是说,可以修改引用类型中操作数的属性(事实就是这样),但不应该。所以不要。好消息是,您的+
操作是正确的。
因此,您必须返回一个new
对象(正如您所做的那样),但当您执行+=
时,您将本地引用分配给该新对象,同时使观察者的引用指向旧,从而导致错误。
您可能想直接修改观察者:
showStats.statsToObserve += nextStats;
或者,你可以完全破解它并这样做(不推荐):
public static Stats operator +(Stats a, Stats b) {
Stats c = new Stats();
c.someField = a.someField + b.someField;
a.SomeField += b.someField; //AHHHH You just modified an operand!
c.someOtherField = a.someOtherField + b.someOtherField;
a.someOtherField += b.someOtherField; //AHHHH You just did it again!
return c;
}
注意:我也很喜欢@DStanley的建议。