在 C# 中构造不可变值类型的字段与属性有什么区别?

问题描述

示例:

public readonly struct Vector3
{
    public readonly float x;
    public readonly float y;
    public readonly float z;

    public Vector3(float x,float y,float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public static readonly Vector3 oneField = new Vector3(1f,1f,1f);
    public static Vector3 oneProperty => new Vector3(1f,1f);

    public static Vector3 operator +(Vector3 lhs,Vector3 rhs) => 
           new Vector3(lhs.x + rhs.x,lhs.y + rhs.y,lhs.z + rhs.z);
}

执行时行为究竟有何不同:

var v = Vector3.oneField + Vector3.oneField

对比

var v = Vector3.oneProperty + Vector3.oneProperty

根据我的理解,当加载(相关部分)程序时,字段的内容被加载并存储在堆/RAM 中,然后在调用 + 运算符时将值从那里复制到堆栈中两次。

虽然属性会在调用 + 运算符时直接在堆栈上分配内存两次。

这样对吗?哪一个在“技术上”更快? (只是好奇细节)

编辑

从技术上讲,我认为它不是一个属性,而只是一个“表达式实体成员”,但这与问题无关,但如果有必要,我会更正以使其清晰。

解决方法

字段被读取;属性被执行

此代码...

var v = Vector3.oneField + Vector3.oneField

...读取两个字段并添加它们。没有创建或分配任何内容(除了存储结果的位置 v,它可以在堆栈上,但也可以在其他地方,例如,如果变量是 closed .).

此代码...

var v = Vector3.oneProperty + Vector3.oneProperty

...执行两个属性并添加它们的结果。因此 oneProperty getter 被执行两次。

由于属性 getter 包含 new 关键字,因此每次调用它时都会执行 new,从而创建一个新实例。因此,在此示例中,创建了 Vector3 的三个实例 - 两个是相加的,一个是相加的结果。