为什么 C# 链表 class 变量在分配后不保留其值?
Why does a C# linked list class variable not retain its value after it's assigned?
我正在创建一个填字游戏生成器,但似乎对网格系统中坐标的简单变量分配有问题。
我有一个非常简单的结构来保存离散坐标值,如下所示。我剥离了封装以使其更易于阅读。
public struct vec2
{
public int x, y;
public vec2(int x, int y)
{
this.x = x;
this.y = y;
}
}
此 Vec2 结构在 class 中维护以保存字值
public struct WordClass
{
string svalue;
bool flag;
public vec2 position;
public WordClass(string sarg, bool barg)
{
this.svalue = sarg;
this.flag = barg;
position = new vec2(0,0);
}
public string StringVal
{
get { return svalue; }
}
public bool FlagVal
{
get { return flag; }
}
public void DisableWord()
{
if (this.flipflop == false)
{
this.flipflop = true;
}
}
public void SetPos(int xa, int ya)
{
this.position.x = xa;
this.position.y = ya;
}
}
这基本上应该维护一个带有使用标志的永久单词列表,以及一个可变位置,因为系统会计算单词的最佳位置。
我有一个动态的单词链表
List<WordClass> WordList = new List<WordClass>();
并更改单词在单词列表中的坐标
//Arbitrary values
WordList[0].SetPos(Position_X, Position_Y);
现在我的问题是,当我尝试使用单词的位置时,无论我之前设置了什么,它都保持默认值 0, 0。我在做其他功能时一直摸不着头脑,这让我想知道我是否遗漏了一些重要的东西。
问题似乎与 vec2
是 ValueObject
这一事实有关,而您正在尝试更改它。有问题的行具体是这两行:
this.position.x = xa;
this.position.y = ya;
为什么?因为 vec2
是一个 struct
每次你读它你得到一个 临时副本 ,然后修改那个副本,然后这个副本被扔掉,而你仍在阅读原始的,未修改的。这就是为什么值对象应该尽可能 不可变 的原因之一,除非你有充分的理由。
第一步应该是制作一个适当的不可变 vec2
结构:
public struct vec2
{
public int x { get; private set; }
public int y { get; private set; }
public vec2(int x, int y)
{
this.x = x;
this.y = y;
}
}
完成后,您需要处理 SetPos
方法中的修改。由于该结构是不可变的,您无法再读取它,而是每次您需要更改它时,您将丢弃当前实例并创建一个新实例:
public void SetPos(int xa, int ya)
{
this.position = new vec2(xa, ya);
}
这将创建一个全新的结构并将其分配给包含新值的内部字段。由于这并没有真正尝试修改结构,而是更改了新结构的结构,因此它不会受到相同的细微错误的影响。
我正在创建一个填字游戏生成器,但似乎对网格系统中坐标的简单变量分配有问题。 我有一个非常简单的结构来保存离散坐标值,如下所示。我剥离了封装以使其更易于阅读。
public struct vec2
{
public int x, y;
public vec2(int x, int y)
{
this.x = x;
this.y = y;
}
}
此 Vec2 结构在 class 中维护以保存字值
public struct WordClass
{
string svalue;
bool flag;
public vec2 position;
public WordClass(string sarg, bool barg)
{
this.svalue = sarg;
this.flag = barg;
position = new vec2(0,0);
}
public string StringVal
{
get { return svalue; }
}
public bool FlagVal
{
get { return flag; }
}
public void DisableWord()
{
if (this.flipflop == false)
{
this.flipflop = true;
}
}
public void SetPos(int xa, int ya)
{
this.position.x = xa;
this.position.y = ya;
}
}
这基本上应该维护一个带有使用标志的永久单词列表,以及一个可变位置,因为系统会计算单词的最佳位置。
我有一个动态的单词链表
List<WordClass> WordList = new List<WordClass>();
并更改单词在单词列表中的坐标
//Arbitrary values
WordList[0].SetPos(Position_X, Position_Y);
现在我的问题是,当我尝试使用单词的位置时,无论我之前设置了什么,它都保持默认值 0, 0。我在做其他功能时一直摸不着头脑,这让我想知道我是否遗漏了一些重要的东西。
问题似乎与 vec2
是 ValueObject
这一事实有关,而您正在尝试更改它。有问题的行具体是这两行:
this.position.x = xa;
this.position.y = ya;
为什么?因为 vec2
是一个 struct
每次你读它你得到一个 临时副本 ,然后修改那个副本,然后这个副本被扔掉,而你仍在阅读原始的,未修改的。这就是为什么值对象应该尽可能 不可变 的原因之一,除非你有充分的理由。
第一步应该是制作一个适当的不可变 vec2
结构:
public struct vec2
{
public int x { get; private set; }
public int y { get; private set; }
public vec2(int x, int y)
{
this.x = x;
this.y = y;
}
}
完成后,您需要处理 SetPos
方法中的修改。由于该结构是不可变的,您无法再读取它,而是每次您需要更改它时,您将丢弃当前实例并创建一个新实例:
public void SetPos(int xa, int ya)
{
this.position = new vec2(xa, ya);
}
这将创建一个全新的结构并将其分配给包含新值的内部字段。由于这并没有真正尝试修改结构,而是更改了新结构的结构,因此它不会受到相同的细微错误的影响。