Question

Say i have a property in a class:

Vector3 position{get; set;}

So i create an instance of that class somewhere and now i want to change position.x, that would be impossible now because the getter and setter set and get the whole object. So i have to make a temporary Vector3 change its values and then assign it.

Normally i would make position a public field so that problem would be solved. But i cant do it in this case because position is an implementation of an interface and interfaces cant have fields.

So how can i solve this the best way.

Edit: Vector3 is a struct so its a value type

Was it helpful?

Solution

IMO, the easiest answer here:

private Vector3 position;
public Vector3 Position {
    get {return position;}
    set {position = value;} // with @Mehrdad's optimisation
}
public float X {
    get {return position.X;}
    set {position.X = value;}
}
public float Y {
    get {return position.Y;}
    set {position.Y = value;}
}
public float Z {
    get {return position.Z;}
    set {position.Z = value;}
}

Now you can change obj.X, obj.Y and obj.Z if you only need to change one dimension, or change obj.Position to change everything.

If you need the name position to implement an interface, then do it explicitly:

Vector3 IWhateverInterface.position {
    get {return position;}
    set {position = value;}
}

OTHER TIPS

Is the straightforward solution somehow not acceptable?

foo.position = new Vector(newX, foo.position.Y, foo.position.Z);

What's wrong with that? It seems perfectly straightforward.

That's one of the issues with mutable value types. You can create a new instance of the value type with the new X value and reassign in to the property. You can make the instance creation easier by providing useful constructors or adding methods that return a modified object (instead of modifying the value).

Pre-P.S.: Saw too late that Vector3 is a value type; the following post therefore won't be of much help. Sorry for that mistake.

Well, while interfaces cannot have fields, they can have properties, e.g.:

interface IVector3
{
    double X { get; set; }
    double Y { get; set; }
    double Z { get; set; }
}

In your Vector3, you simply implement those like everything else:

class Vector3 : IVector3
{
    double IVector3.X
    {
        get { ... }
        set { ... } 
    }
    ...
}

Now back to your position property. You tie the property to a fixed instance during initialization and only provide a getter:

Vector3 position
{
    get
    {
        return _position;
    }
}

private Vector3 _position = new Vector3(...);

By making the property read-only (ie. no setter), you ensure that it won't be replaced with a new Vector3 object. Instead, you tie it to a fixed instance (_position) at initialization time. But you can change the Vector3 by assigning new values to position.X, position.Y, or position.Z.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top