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;
The problem is, that the getter returns a copy of Vector2
. If you change the coordinates like this
obj.Position.X = x;
obj.Position.Y = y;
You only change the coordinates of this ephemeral copy.
Do this instead
obj.Position = new Vector2(x, y);
This has nothing to do with by value or by reference. Value2
is a value type and get
returns this value. If the vector had a reference type (class), get
would return this reference. return
returns values by value. If we have a reference type, then these references are the values and are returned.
Every storage location of a structure type holds all the fields, private and public, of that struct. Passing a parameter of a structure type entails allocating space for that structure on the stack and copying all of the fields from the structure to the stack.
With regard to working with structures stored within a collection, using mutable structs with the existing collections generally requires reading out a struct to a local copy, mutating that copy, and the storing it back. Assuming MyList is a List<Point>
, and one wants to add some local variable z
to MyList[3].X
:
Point temp = MyList[3]; temp.X += Z; MyList[3] = temp;
This is mildly annoying, but is often cleaner, safer, and more efficient than using immutable structs, way more efficient than immutable class objects, and way safer than using mutable class objects. I'd really like to see compiler support for a better way for collections to expose value-type elements. There are ways of writing efficient code to handle such exposure with good semantics (e.g. a collection object could react when elements were updated, without requiring those elements to have any link to the collection) but the code reads horribly. Adding compiler support in a manner conceptually similar to closures would allow efficient code to also be readable.
Note that contrary to what some people claim, a structure is fundamentally different from a class-type object, but for every structure type there is a corresponding type, sometimes referred to as a "boxed structure", which derives from Object (see the CLI (Common Language Infrastructure) specification, sections 8.2.4 and 8.9.7). Although the compiler will implicitly convert any struct into its corresponding boxed type when necessary to pass it to code that expects a reference to a class-type object, will allow references to boxed structs to have their contents copied into real structs, and will sometimes allow code to work with boxed structs directly, boxed structs behave like class objects, because that's what they are.
A struct
is a value type, so it's always passed as a value.
A value can either be a reference type (object) or a value type (struct). What's passed around is always a value; for a reference type you pass the value of the reference to it, for a value type you pass the value itself.
The term by reference is used when you use the ref
or out
keywords to pass a parameter. Then you are passing a reference to the variable that contains the value instead of passing the value. Normally a parameter is always passed by value.