我对C#很陌生,我还在搞清楚事情。 我的问题是我有一个这样的课程:
class Sprite {
private Vector3 _position;
public Vector3 Position {
get { return _position; }
set { _position = value;
HandleEvent(); }
}
public Sprite() {
_position = new Vector3();
}
}
使用Vector3对象和get / set块。 这是Vector3结构的简化版本:
struct Vector3 {
float X, Y, Z;
}
现在我的问题是,如果我这样做:
Sprite sprite = new Sprite();
sprite.Position.X += 4.0F;
它给了我一个错误,因为位置不是变量,而是由吸气剂给我。但我不想公开_position,因为我想在变量发生变化时处理事件。
(在Java中,这非常有效,这就是为什么我感到困惑:/)
你可以给我一个暗示我做错了什么或你会做些什么不同的事情?
修改
是的,Vector3是一个结构而不是一个类。很抱歉这个混乱,但我对C#很新。
答案 0 :(得分:3)
(在Java中,这非常有效,这就是为什么我感到困惑:/)
Java没有C#调用struct
。
在C#中,struct
会创建value type。当您从属性getter返回值类型时,您不会在某处返回对已存在对象的引用,而是返回该值的全新副本。因此,修改该值的副本是没有意义的:没有人会看到修改。
在Java中,您可以使用class
。在C#中,您也可以这样做。这会创建一个引用类型。当您从属性getter返回引用类型时,您不会返回所有对象字段的副本,只需返回对同一对象的引用。在这里,修改确实有意义。您有多个对同一对象的引用,并且通过任何其他引用仍可以看到修改。
答案 1 :(得分:1)
应该正常工作。该示例编译:
namespace ConsoleApplication8
{
class Sprite
{
private Vector3 _position;
public Vector3 Position
{
get { return _position; }
set
{
_position = value;
// HandleEvent();
}
}
public Sprite()
{
_position = new Vector3();
}
}
class Vector3
{
public float X, Y, Z;
}
class Program
{
static void Main()
{
Sprite sprite = new Sprite();
sprite.Position.X += 4.0F;
}
}
}
由于你的向量似乎是一个结构,因为结构是一个值类型(这意味着你的被调用的getter将返回你职位的副本)你无法操作你的getter回报。您需要创建一个新的Vector并将其作为一个整体分配。请注意,这似乎是为您制作的优化。如果Vector对象定义属于您,只需将其设为一个类,这样它就像您习惯使用Java一样。
如果想要这是一个结构,你必须创建一个新结构并分配它:
sprite.Position = new Vector
{
X = sprite.Position.X + 4.0F,
Y = sprite.Position.Y,
Z = sprite.Position.Z
};
答案 2 :(得分:1)
因为Vector3
是一个结构,所以它会被隐式复制。例如,以下代码创建两个向量,而不是一个:
Vector3 tmp1 = new Vector3();
Vector3 tmp2 = tmp1;
如果您主要习惯于没有复制并且未创建实例的类,除非您明确说明(例如,使用new
),否则这可能会造成混淆。
将上述内容与C#属性作为方法的语法糖这一事实相结合,您将得到答案。这样:
Sprite sprite = new Sprite();
sprite.Position.X += 4.0F;
就像这样:
Sprite sprite = new Sprite();
sprite.get_Position().X += 4.0F;
将执行以下操作:
Sprite sprite = new Sprite();
Vector3 tmp1 = sprite.get_Position();
tmp1.X += 4.0F;
请注意tmp1
是一个全新的Vector3
。它在各个方面与sprite.Position
无关,除了它们在某些点上包含相等坐标的事实。
更改该临时Vector3
不会对该属性返回的Vector3
产生影响。 C#编译器意识到这种不幸的模式,并拒绝编译它,因为它几乎肯定不是你想要的。
要解决这个问题,你可以尝试明确地采取这个位置,就像上面一样,然后明确地把它放回去:
Sprite sprite = new Sprite();
Vector3 tmp1 = sprite.Position;
tmp1.X += 4.0F;
sprite.Position = tmp1;
一般来说,出于这样的原因,你应该避免使用可变结构。
Java没有这个问题,因为它根本没有结构。
答案 3 :(得分:0)
试试这个:
Sprite sprite = new Sprite();
Vector3 v = sprite.Position;
v.X += 0.4F;
sprite.Position = v;
错误原因:
问题是sprite.Position
返回一个结构,所以当你访问它时,它会因值语义而创建它的副本。 + =尝试修改该值,但它将修改临时副本 - 而不是存储在sprite
中的实际结构。
您必须从读取位置获取值并将其放入局部变量,更改该局部变量,然后将局部变量分配回位置。