C# - 如何修改 getter 给出的结构?
C# - How can I modify a struct given by a getter?
我是 C# 的新手,我还在摸索。
我的问题是我有这样的 class:
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 不是一个变量,而是 getter 给我的。但是我不想做_position public,因为我想在变量改变时处理一个事件。
(在 Java 中这非常有效,这就是我感到困惑的原因:/)
你能告诉我我做错了什么或者你会做些什么吗?
编辑:
是的,Vector3 是一个结构而不是 class。抱歉造成混淆,但我是 C# 的新手。
它应该工作正常。本示例编译:
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 被调用将 return a copy 你的位置)你不能对你的 getter return 进行操作。您将需要创建一个新的 Vector 并将其作为一个整体进行分配。请注意,这似乎是 优化 某人为您制作的。如果 Vector 对象定义属于您,只需将其设为 class,这样它的工作方式就像您习惯于 Java.
如果您希望这是一个结构,您将必须创建一个新结构并分配给它:
sprite.Position = new Vector
{
X = sprite.Position.X + 4.0F,
Y = sprite.Position.Y,
Z = sprite.Position.Z
};
试试这个:
Sprite sprite = new Sprite();
Vector3 v = sprite.Position;
v.X += 0.4F;
sprite.Position = v;
错误原因:
问题是 sprite.Position
returns 一个结构,因此当您访问它时,由于值语义,它会创建它的副本。 += 尝试修改该值,但它会修改一个临时副本 - 而不是存储在 sprite
.
中的实际结构
您必须从读取 Position 中获取值并将其放入局部变量,更改该局部变量,然后将局部变量赋值回 Position。
(In Java this works perfectly, that's why I'm confused :/)
Java 没有 C# 调用的 struct
.
在 C# 中,struct
创建一个 value type。当你 return 来自 属性 getter 的值类型时,你不会 return 对某处已经存在的对象的引用,你 return 一个全新的值的副本。因此,修改该值的副本没有意义:没有人会看到修改。
在 Java 中,您将为此使用 class
。在 C# 中,您可以执行相同的操作。这创建了一个引用类型。当您 return 来自 属性 getter 的引用类型时,您不会 return 对象所有字段的副本,您只是 return 一个引用到同一个对象。在这里,修改确实有意义。您对同一个对象有多个引用,并且通过任何其他引用仍然可以看到修改。
因为 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 没有这个问题,因为它根本没有结构。
我是 C# 的新手,我还在摸索。 我的问题是我有这样的 class:
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 不是一个变量,而是 getter 给我的。但是我不想做_position public,因为我想在变量改变时处理一个事件。
(在 Java 中这非常有效,这就是我感到困惑的原因:/)
你能告诉我我做错了什么或者你会做些什么吗?
编辑:
是的,Vector3 是一个结构而不是 class。抱歉造成混淆,但我是 C# 的新手。
它应该工作正常。本示例编译:
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 被调用将 return a copy 你的位置)你不能对你的 getter return 进行操作。您将需要创建一个新的 Vector 并将其作为一个整体进行分配。请注意,这似乎是 优化 某人为您制作的。如果 Vector 对象定义属于您,只需将其设为 class,这样它的工作方式就像您习惯于 Java.
如果您希望这是一个结构,您将必须创建一个新结构并分配给它:
sprite.Position = new Vector
{
X = sprite.Position.X + 4.0F,
Y = sprite.Position.Y,
Z = sprite.Position.Z
};
试试这个:
Sprite sprite = new Sprite();
Vector3 v = sprite.Position;
v.X += 0.4F;
sprite.Position = v;
错误原因:
问题是 sprite.Position
returns 一个结构,因此当您访问它时,由于值语义,它会创建它的副本。 += 尝试修改该值,但它会修改一个临时副本 - 而不是存储在 sprite
.
您必须从读取 Position 中获取值并将其放入局部变量,更改该局部变量,然后将局部变量赋值回 Position。
(In Java this works perfectly, that's why I'm confused :/)
Java 没有 C# 调用的 struct
.
在 C# 中,struct
创建一个 value type。当你 return 来自 属性 getter 的值类型时,你不会 return 对某处已经存在的对象的引用,你 return 一个全新的值的副本。因此,修改该值的副本没有意义:没有人会看到修改。
在 Java 中,您将为此使用 class
。在 C# 中,您可以执行相同的操作。这创建了一个引用类型。当您 return 来自 属性 getter 的引用类型时,您不会 return 对象所有字段的副本,您只是 return 一个引用到同一个对象。在这里,修改确实有意义。您对同一个对象有多个引用,并且通过任何其他引用仍然可以看到修改。
因为 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 没有这个问题,因为它根本没有结构。