C# 在属性getter中求值还是在创建实例时求值?

C# 在属性getter中求值还是在创建实例时求值?,c#,C#,好的,一个简单的问题 首先,我必须说,我关心的不是绩效。我完全知道,无论一个选项或另一个选项可能带来什么性能成本,都可能毫无意义,甚至不值得在正常情况下考虑。它更多的是与设计标准和好奇心有关,因为大多数程序员都会这样做 好的,问题很简单: 假设我有一个ComplexNumberstruct,可以通过以下方式实现: public struct Complex : IEquatable<Complex>, IFormattable { readonly double realPa

好的,一个简单的问题

首先,我必须说,我关心的不是绩效。我完全知道,无论一个选项或另一个选项可能带来什么性能成本,都可能毫无意义,甚至不值得在正常情况下考虑。它更多的是与设计标准和好奇心有关,因为大多数程序员都会这样做

好的,问题很简单:

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

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; } }
    ...
 }
public struct Complex:IEquatable,IFormattable
{
只读双实部、虚部、量值、参数;
只读静态复合体j=新复合体(0,1);
公共综合体(双真实部分、双想象部分)
{
this.realPart=realPart;
this.imaginaryPart=imaginaryPart;
this.magnity=Math.Sqrt(Math.Pow(realPart,2)+Math.Pow(imaginaryPart,2));
this.argument=Math.Atan2(想象部分,现实部分);
}
公共双RealPart{get{返回this.RealPart;}}
公共双ImageAryPart{get{返回this.ImageAryPart;}}
公共双量级{get{返回this.magnity;}
公共双参数{get{返回this.Argument;}}
公共静态复数J{get{return Complex.J;}}
...
}
幅值
参数
属性具有在构造时计算的支持字段。另一种选择是简单地计算两个getter中相应的值

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

[更新如下:]

为什么在getter中进行评估而不是setter中进行评估?我会在设置值时对其进行评估。这样就可以在私有方法中使用正确的值

在c'tor中设置默认值,在setter中评估

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

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

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

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

然而,getter的合同说它将获得价值。所以在吸气剂块中应尽量避免计算部分

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


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

我倾向于直接在getter中计算值,因为它更具可读性:如果您想知道
参数
的作用,只需查看它的代码即可。如果像现在一样将值缓存在字段中,则必须转到
Argument
property→ <代码>参数
字段→ 构造器


如果性能真的很重要,那么很显然,在您的案例中,找出哪个选项更好的正确方法是分析。但是作为猜测,我认为在字段中缓存值的版本也会变慢,特别是如果您不经常使用计算值的话。这是因为
struct
s一直被复制,这些字段使
struct
的大小增加了一倍。

我不明白你的意思。这是一个不可变的类型,没有setter。问题是选择在构造函数中初始化相应字段,然后通过getter使其可用,还是选择没有支持字段并在getter中每次求值。@在这两者之间,不,我不明白。你在回答中说的是二传手。@svick:对不起,我的评论是针对霍夫纳威利的。在我的问题中,我绝对不是在谈论setter。是的,我已经修改了我的答案,因为我现在看到你们在谈论只读属性。请看上面的答案。问题不是关于初始化成员变量。当涉及到值类型时,这个问题是没有意义的,因为必须这样做。问题是是否值得从成员变量开始。我不同意在getter中应该避免计算。特别是当它是像这里这样相对简单的代码时。@InBetween:是的,如果内存不是问题的话。随着需求的变化,它将更具可扩展性。@svick:好吧,实际答案是,这要看情况而定。但是,如果可能的话,大多数时候我们都应该这样做。可读的代码总是一个优点,是的,让getter来完成这项工作确实会使代码更容易阅读,并且一眼就能看出它在做什么。当然,在这样一个简单的类型中,这可能是一个次要因素,但仍然需要记住。@svick:如果只考虑这段代码,那么将代码放入getter就可以了。但一般来说,我不喜欢这样。