在属性getter中或创建实例时求值

本文关键字:实例 创建 属性 getter | 更新日期: 2023-09-27 18:22:10

好的,这是一个简单的问题。

首先,我不得不说,我关心的不是性能。我完全意识到,无论一种或另一种选择可能带来什么性能成本,都可能毫无意义,甚至在正常情况下都不值得考虑。这更多地与设计标准有关,也与大多数程序员如何做到这一点有关

好的,所以问题很简单:

假设我有一个ComplexNumberstruct,我可以通过以下方式实现它:

public struct Complex : IEquatable<Complex>, IFormattable
{
    readonly double realPart, imaginaryPart, magnitude, argument;
    readonly static Complex j = new Complex(0, 1);
    public Complex(double realPart, double imaginaryPart)
    {
        this.realPart = realPart;
        this.imaginaryPart = imaginaryPart;
        this.magnitude = Math.Sqrt(Math.Pow(realPart, 2) + Math.Pow(imaginaryPart, 2));
        this.argument = Math.Atan2(imaginaryPart, realPart);
    }
    public double RealPart { get { return this.realPart; } }
    public double ImaginaryPart { get { return this.imaginaryPart; } }
    public double Magnitude { get { return this.magnitude; } }
    public double Argument { get { return this.argument; } }
    public static Complex J { get { return Complex.j; } }
    ...
 }

MagnitudeArgument属性具有在构建时评估的后备字段。另一种选择是简单地评估任一getter中的相应值。

最推荐的方法是什么?是否有任何编码标准可以为制定标准而推荐任何选项?如果没有,通常首选是什么?还是仅仅取决于性能,在我的情况下这是无关紧要的?

在属性getter中或创建实例时求值

我更喜欢直接在getter中计算值,因为它更可读:如果你想知道Argument的作用,只需看看它的代码。如果像现在这样将值缓存在字段中,则必须转到Argument属性→argument字段→构造函数。

如果性能确实很重要,那么很明显,在您的情况下,找出哪个选项更好的正确方法是分析。但正如猜测的,我认为在字段中缓存值的版本也会更慢,尤其是如果你不经常使用计算值的话。这是因为struct总是被复制,而这些字段使struct的大小增加了一倍。

[更新如下:]

为什么在getter中求值而不在setter中求值?我会在设置时评估该值。这样,可以在私有方法中使用正确的值。

在c'tor中设置默认值,在setter中求值。

您读取值的频率总是高于设置值的频率,因此出于性能原因,您应该在setter中进行评估——它的运行频率会更低。

[更新:]如果属性是只读的,则在c'tor中进行求值,原因与上面相同(性能-您只会进行一次求值)。我知道你说表现不是问题,但如果没有理由不以更好的表现方式来做,那么就应该这样做。

C'tor应使用默认值初始化成员。

毫无疑问,如果将代码转移到getter,性能可能会成为问题,因为每次调用getter时都要进行评估。

然而,getter的合同说它会得到价值。因此,在getter块中应尽量避免计算部分。

您还应该尽量避免使用脏值。如果您在getter中设置了Magnitude,但尝试直接在类中访问它;您最终可能会使用错误的值。

因此,如果问题是关于初始化成员变量,请在c'或中执行。这就是为什么它是由语言设计师创建的。