可以得到“;运算符“;后果

本文关键字:后果 运算符 | 更新日期: 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的建议。