1

If I have a Struct or a Class, lets say I'm using a Vector2 (which has two members, float X and float Y), how am I supposed to properly get/set its methods in a class?

This is the code I know of right now:

public class MyClass
{
    private Vector2 vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }
}

But what if I wanted to edit the members (or certain members) of the Vector2 with the set method? Something like this is what I'm asking for:

set.X
{
    vector.X = value.X;
}
set.Y
{
    vector.Y = value.Y;
}

And it would be called as simply as Vector.X = 5. I thought up an alternative, using something like public float VectorX { set { vector.X = value; } } but I would prefer a more logical and object-orientated way. Is there?

James Hurley
  • 833
  • 1
  • 10
  • 33

3 Answers3

1

It makes a BIG difference whether Vector2 is a class or a struct.

Since Vector2 is a class you can simply do

obj.Vector.X = 5;

having

public class MyClass
{
    private Vector2 _vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }
}

If, however Vector2 was a struct then you cannot modify the return value from the get. If you try you will get a compile error:

Cannot modify the return value of ... because it is not a variable.

You can work around this using the method you suggested with

public float VectorX
{
    get { return _vector.X; }
    set { _vector.X = value; }
}

public float VectorY
{
    get { return _vector.Y; }
    set { _vector.Y = value; }
}

or you could provide a wrapper class around Vector2 like:

class Vector2Wrapper
{
    public Vector2 Vector;
}

and then store a Vector2Wrapper in MyClass like

public class MyClass
{
    private Vector2Wrapper _vector2Wrapper;
    public Vector2Wrapper VectorWrapper
    {
        get { return _vector2Wrapper; }
        set { _vector2Wrapper= value; }
    }
}

and you can then modify it like

obj.VectorWrapper.Vector.X = 5;
mclaassen
  • 5,018
  • 4
  • 30
  • 52
  • Thank you, this absolutely clears up any confusion that I had--I am used to writing in C++ and didn't take into consideration that classes are always references. – James Hurley Jun 25 '14 at 18:51
0

you can't specify a submethod to handle that partial set, because that set is handled by the Vector class and us thus out of your scope. the moment someone calls Myobject.Vector they are calling your get funcion, but when it moves on to .X they are calling the Vector.get_X function.

This may be easier to see by looking at the compiled code using the ILDasm tool, which reveals the actual method calls your properties make sugar out of.

Now, what you CAN do is to wrap certain properties, as mentioned. The result would like like so.

public class MyClass
{
    private Vector2 _vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }

    public float VectorX
    {
        get { return _vector.X; }
        set { _vector.X = value; }
    }

    public float VectorY
    {
        get { return _vector.Y; }
        set { _vector.Y = value; }
    }
}

Another option might be to use the pattern of INotifyPropertyChanged in your Vector class, raising an event every change which your MyClass can then listen to and react to, thus applying logic when child elements are updated.

There is also the option of using an indexer property

public class MyClass
{
    public enum Axis { X, Y }

    private Vector2 _vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }

    public float this[Axis axis]
    {
        get { return axis == Axis.X ? vector.x : vector.y; }
        set
        {
            if(axis == Axis.Y)
            {
                // Special logic here
                vector.Y = value;
            }

            if(axis == Axis.X)
            {
                // Special logic here
                vector.X = value;
            }
        }
    }
}
David
  • 10,458
  • 1
  • 28
  • 40
  • I had hoped this wasn't the case and that I was missing some basic syntax... Oh well. – James Hurley Jun 25 '14 at 18:05
  • Glad I could help, even if it wasn't the answer you wanted. I hope one of my alternatives helps, and I have one more to intefgrate to my answer... – David Jun 25 '14 at 18:18
0

Because Vector2 is a struct, you are getting a COPY. You need to use the setter to set a new Vector2. There are 2 ways:

Vector2 v = myClass.Vector; //get a copy of the vector
v.X = 5f; // change its value
myClass.Vector = v; // put it back

I don't really like the following, but it's one statement:

    myClass.Vector = new Vector2(2f, myClass.Vector.Y)

Inside MyClass, you can create a property that sets only the X value:

public float X {
    get { return Vector.X; }
    set {
        Vector2 v = Vector;
        v.X = value;
        Vector = v;
    }
}

(Vector can be an automatic property)

Dennis_E
  • 8,751
  • 23
  • 29