Reputation: 572
I have a structure defined as:
public struct MpPoint
{
public Vector3 pos;
public bool isOn;
public MpPoint(Vector3 p, bool e){pos = p; isOn = e;}
public static Vector3 operator + (MpPoint p0, MpPoint p1) => p0.pos + p1.pos;
public static Vector3 operator - (MpPoint p0, MpPoint p1) => p0.pos - p1.pos;
// public void Update(Vector3 newp) => pos = newp; // <- This does not work
// public void Update(Vector3 newp) => pos = new Vector3(newp.x,newp.y,newp.z); // <-this does not work either
// public void Update(Vector3 newp) => this = new MpPoint( new Vector3(newp.x,newp.y,newp.z), isOn); // <- even this does not work
}
And I keep it in a list. The only way I manage to update it is from the outside like this:
var pOld = pts[p];
var pNew = pOld.pos * factor;
pts[p] = new MpPoint(pNew, pOld.isOn);
How can I create the Update function inside the struct, so I can replace this ugly code with something like pts[p].Update(factor);
or something alike?
Upvotes: 0
Views: 996
Reputation: 3182
This is basically a question about the nature of value types. When you retrieve a value type from a collection, you are getting a copy of the object rather than the object itself. That means that nothing you do to that copy, whether it be via a field, property or method, is going to affect the original object. That means that you have no choice but to get the copy from the collection, make your change(s) to that copy and then set the collection item to overwrite the original object. In your case, it really should have been like so:
var pOld = pts[p];
pOld.pos *= factor;
pts[p] = pOld;
You simply update the copy and then write the copy over the original.
If you used a class rather than a structure then indexing the collection would be creating a copy of a reference rather than a value and that reference will still refer to the original object. That means that you can modify an object directly in the collection, e.g.
pts[p].pos *= factor;
Interestingly, if you were using an array rather than a collection, you'd be able to do that with structures too. That's because indexing an array provides access to the original value rather than a copy.
With a collection of structures, you have no choice but to assign something back to the collection item, no matter how you make the change. If you were to follow the rules about structures being immutable and methods that "change" them returning a new instance then your type ought to look like this:
public readonly struct MpPoint
{
public Vector3 Pos { get; }
public bool IsOn { get; }
public MpPoint(Vector3 p, bool e) { Pos = p; IsOn = e; }
public MpPoint Update(int factor) => new MpPoint(Pos * factor, IsOn);
public static Vector3 operator +(MpPoint p0, MpPoint p1) => p0.Pos + p1.Pos;
public static Vector3 operator -(MpPoint p0, MpPoint p1) => p0.Pos - p1.Pos;
}
and then you could do this:
pts[p] = pts[p].Update(factor);
Upvotes: 1