Are structs 'pass-by-value'?

c#, pass-by-value, struct

Solution

It is important to realise that everything in C# is passed by value, unless you specify `ref` or `out` in the signature.

What makes value types (and hence `struct`s) different from reference types is that a value type is accessed directly, while a reference type is accessed via its reference. If you pass a reference type into a method, its reference, not the value itself, is passed by value.

To illustrate, imagine we have a class `PointClass` and a struct `PointStruct`, defined analogously (omitting irrelevant details):

struct PointStruct { public int x, y; }

class PointClass { public int x, y; }

And we have a method `SomeMethod` that takes these two types by value:

static void ExampleMethod(PointClass apc, PointStruct aps) { … }

If we now create two objects and call the method:

var pc = new PointClass(1, 1);
var ps = new PointStruct(1, 1);

ExampleMethod(pc, ps);

… we can visualise this with the following diagram:

Since `pc` is a reference, it doesn’t contain the value in itself; rather, it references an (unnamed) value somewhere else in memory. This is visualised by the dashed border and the arrow.

But: for both `pc` and `ps`, the actual variable is copied when calling the method.

What happens if `ExampleMethod` reassigns the argument variables internally? Let’s check:

static void ExampleMethod(PointClass apc, PointStruct aps); {
    apc = new PointClass(2, 2);
    aps = new PointStruct(2, 2);
}

Output of `pc` and `ps` after calling the method:

pc: {x: 1, y: 1}
ps: {x: 1, y: 1}

→ `ExampleMethod` changed a copy of the values, and the original values are unaffected.

This, fundamentally, is what “pass by value” means.

There’s still a difference between reference and value types, and that comes into play when modifying members of the value, not the variable itself. This is the part that trips people up when they are confronted with the fact that reference types are passed by value. Consider a different `ExampleMethod`.

static void ExampleMethod(PointClass apc, PointStruct aps) {
    apc.x = 2;
    aps.x = 2;
}

Now we observe the following result after calling the method:

pc: {x: 2, y: 1}
ps: {x: 1, y: 1}

→ The reference object was changed, whereas the value object wasn’t. The diagram above shows why that is: for the reference object, even though `pc` was copied, the actual value that both `pc` and `apc` reference remains identical, and we can modify that via `apc`. As for `ps`, we copied the actual value itself into `aps`; the original value cannot be touched by `ExampleMethod`.

Problem

I've recently tried to create a property for a `Vector2` field, just to realize that it doesn't work as intended. ``` public Vector2 Position { get; set; } ``` this prevents me from changing the values of its members (`X` & `Y`) Looking up information on this, I read that creating a property to a `Vector2` struct returns only a copy of the original object and not a reference. As a Java developer this confuses me. When are objects in C# passed by value and when are they passed by reference? Are all struct objects passed by value?

Original source

Related problems