Reputation: 11883
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!
Upvotes: 1
Views: 999
Reputation: 13055
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.
Upvotes: 0
Reputation: 1499760
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.
Upvotes: 4