我想知道C#属性是否可以实现以下功能。
我有一个“Transform”类,它在私有成员字段中保存一个4x4矩阵。现在我想创建一个这样的属性:
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; }
}
但我想提供以下功能:
Transform myTransform = new Transform();
myTransform.Position.X += 3.0f;
这样可以直接更改属性,就好像它是一个变量一样。用C#以某种方式可能吗? (Vector3和Matrix都是结构。)
谢谢!
答案 0 :(得分:4)
不,这不起作用。想一想 - 你的getter和setter真的做的东西。你不能在不完全改变语义的情况下绕过它们,我不会指望一个setter只是因为我改变了getter返回的内容而运行。
你真的 拥有可变结构吗?你会发现各种角落的情况和怪异。为什么不让它们变成不可变的,写一下:
myTransform.Position = myTransform.Position.OffsetBy(3.0f, 0f, 0f);
或
myTransform.OffSetPosition(3.0f, 0f, 0f);
这样可以避免首先构建Vector3
。
可变结构很少是正确的解决方案。在极少数情况下,由于性能原因,可能是合理的,但我会首先探索所有其他选项。
答案 1 :(得分:0)
正如乔恩所说,这只是一个坏主意。每当你处理简单的值类型(并且Vector3符合条件)时,你最好不要让它们成为不可变的。
如果你真的认真,你可以关闭到你想要的东西,但这需要一些工作。
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);
}
话虽如此,不会这样做。我会立即拒绝任何包含此类代码的代码审核。