views:

241

answers:

2

hey there!

I'd like to know whether the following is possible with C# properties.

I have a class "Transform" that holds a 4x4 matrix in a private member field. Now I want to create a property like this:

    Matrix m;
    public Vector3 Position
    {
        get { return new Vector3(m[12], m[13], m[14]); }
        set { m[12] = value.X; m[13] = value.Y; m[14] = value.Z; }
    }

but i'd like to provide the following functionality:

    Transform myTransform = new Transform();
    myTransform.Position.X += 3.0f;

such that the Property directly can be changed as if it was a variable. is this somehow possible with C#? (Vector3 and Matrix both are structs.)

thanks!

+4  A: 

No, this won't work. Think about it - your getters and setters are really doing something. You can't bypass them without changing the semantics completely, and I wouldn't expect a setter to run just because I changed something in what the getter had returned.

Do you really have to have mutable structs to start with? You'll find all kinds of corner cases and weirdnesses. Why not make them immutable, and write:

myTransform.Position = myTransform.Position.OffsetBy(3.0f, 0f, 0f);

or

myTransform.OffSetPosition(3.0f, 0f, 0f);

That would save you having to build the Vector3 in the first place.

Mutable structs are very, very rarely the right solution. In a very few cases they may be reasonable for performance reasons, but I'd explore all other options first.

Jon Skeet
you should have business hours, so that the rest of us know when to bother answering questions... :D
Nader Shirazie
I'm off to bed right now. Also see http://meta.stackoverflow.com/questions/555
Jon Skeet
hey Jon!yeah sure, i add those functions too, but if it is possible i'd like to offer the possibility to change them directly just for convenience. I just thoght that it technically should be easy to implement the functionality of automatically creating a copy of the property value, change the content of it and then reassign it - so i expected it to be possible somehow...
Mat
A: 

As Jon said, it's just a bad idea. Whenever you're dealing with simple value types (and a Vector3 qualifies), you're better off making them immutable.

If you're really determined, you can get close to what you want, but it takes some work.

public struct Vector3
{
    public Vector3(float X, float Y, float Z, VectorListener listener)
    {
        m_x = X;
        m_y = Y;
        m_z = Z;
        m_listener = listener;
    }
    private VectorListener m_listener;
    private float m_x;
    private float m_y;
    private float m_z;

    public float X
    {
        get{return m_x;}
        set{ m_x = value; m_listener.SetVector(this);}
    }
    public float Y
    {
        get { return m_y; }
        set { m_y = value; m_listener.SetVector(this); }
    }
    public float Z
    {
        get { return m_z; }
        set { m_z = value; m_listener.SetVector(this); }
    }

}
public interface VectorListener
{
    void SetVector(Vector3 vec);
}
public class Transform : VectorListener
{
    private bool m_receivedUpdate;
    public Vector3 MyVector { get{return new Vector3(1.0f, 1.0f, 1.0f, this);} }
    public void SetVector(Vector3 vec)
    {
        ReceivedUpdate = true;
    }
    public bool ReceivedUpdate { get; set; }
}

    // and the test... test class omitted for brevity
    [TestMethod]
    public void TestMethod1()
    {
        Transform transform = new Transform();
        Assert.IsFalse(transform.ReceivedUpdate);

        // the following won't compile
        //transform.MyVector.X = 3.0f;

        // but this will work
        Vector3 vec = transform.MyVector;
        vec.X = 3.0f;
        Assert.IsTrue(transform.ReceivedUpdate);

    }

That being said, don't do this. I would immediately reject any code review that contained code like this.

kyoryu