-1

Example:

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, 1f);

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

How exactly does the behaviour differ when doing:

var v = Vector3.oneField + Vector3.oneField

vs

var v = Vector3.oneProperty + Vector3.oneProperty

From my understanding the content of the field is loaded and stored in the Heap/RAM when the (relevant part of the) program is loaded, the value is then copied from there into the stack twice when the + operator is called.

While the property will allocate the memory directly on the stack twice when the + operator is called.

Is that correct? And which one would be 'technically' faster? (just curious about the details)

EDIT

I think technically its not a property but just an "expression-bodied member", however thats irrelevant for the question, but I will correct it for clarity if necessary.

  • @GuruStron Then where is the content of a field for a struct stored when loaded into RAM? Or am I fundamentally misunderstanding how structs/classes get compiled, saved and loaded for execution? – TheHelpfulHelper Feb 15 '21 at 18:36
  • 4
    `public static Vector3 oneProperty => new Vector3(1f, 1f, 1f);` is a property, but it will return a new instance each time it is called. `public static Vector3 oneProperty { get; } = new Vector3(1f, 1f, 1f);` will only initialize one. Not that it matters a lot in this case. – Dennis_E Feb 15 '21 at 18:37
  • On stack, not heap. Unless boxed/being part of reference type structs (value type) are placed on stack. – Guru Stron Feb 15 '21 at 18:37
  • `oneField` is instantiating a new `Vector3` only one time and use it every time, while `oneProperty` is instantiating a new one everytime it is called. – Magnetron Feb 15 '21 at 18:38
  • @GuruStron It was explained to me that the Stack is specifically for short-lived objects, that are used in the current program execution and is a temporary space for objects to be processed. However a field lives as long as the program is loaded. It would therefor occupy stack space until the program finishes execution? – TheHelpfulHelper Feb 15 '21 at 18:44
  • @TheHelpfulHelper yes, you are correct, my bad, `oneField` is static field one so it will be placed in heap (but should be in [gen 2](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals#generations)) and value will be copied to stack. – Guru Stron Feb 15 '21 at 18:47
  • @TheHelpfulHelper as for being faster, you should check yourself but I would say the first one should be faster but in most cases difference should be negligible. – Guru Stron Feb 15 '21 at 18:49
  • @GuruStron Ahh right I was implicitly thinking about a static field, not an instance field. Thanks for the clarification. Also Im specifically interested in the implementation details of the CLR / JIT Compiler, because it helps me understand how these things work. – TheHelpfulHelper Feb 15 '21 at 18:49
  • https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBLANgHwAEAmARgFgAoKwgZgAJYBDAEwgDtcBPegZwygBXMBnoA1GCOi0qAbyr1F9OoxisO3egDNcEJqIQBuBUpXM2nHjr2iuxykuUNzGq7v30AXvZOKVEqShaAAprDwQ0bXdbSLDRTwBKX3p5B0clDAALbF4AOgR6AF56I2THLJzcnmK7MozsvM8ir3tHAF8qZJVCUiRVdUtxSQxpeg4YADFsGFwWZvYYAHchwJDSLUj1za0E1tMGHr6AkaCxhYAFKAgABxgoDGqAPnoF5ePpYK36L/XdzrS/AdeisTgwbnd9NB6ABqYLvU64TK8SLw5xIhJFZ51dKvEEfRF5ArQxhI/KRAlVGEkvJccmkprEqD0v6UDrUSjdYj0ABCEGA9DkXWIxGSqXSSgAbkwoPQJc1UblxlMZnNiQqldNZntxVKZRKucV1Rcrrd7jw1cNpIrjeCzdr6Gy2VQgA= – mjwills Feb 15 '21 at 20:10
  • The fundamental mechanical difference between your field and property is that the property is declared with a _method_ body, which is executed each time it's called. Note that you could have used `Vector3 oneProperty { get; } = new Vector3(1f, 1f, 1f);` instead, which is still a property and retains property semantics, but _mechanically_ would be identical to the field (simple property getters like that are inlined at JIT compile time), See duplicates for elaboration on this explanation and other details distinguishing fields and properties. – Peter Duniho Feb 16 '21 at 00:18

1 Answers1

-1

Fields are read; properties are executed.

This code...

var v = Vector3.oneField + Vector3.oneField

...reads two fields and adds them. Nothing is created or allocated (except a location to store the result, v, which could be on the stack but could also be somewhere else, e.g. if the variable is closed.).

This code...

var v = Vector3.oneProperty + Vector3.oneProperty

...executes two properties and adds their results. Thus the oneProperty getter is executed twice.

Because the property getter contains the new keyword, it is going to execute new each time it is called, which creates a new instance. So in this example, three instances of Vector3 are created-- two that are added and one that is the result of the addition.

John Wu
  • 50,556
  • 8
  • 44
  • 80