【问题标题】:Public variable of struct is not changing [duplicate]结构的公共变量没有改变[重复]
【发布时间】:2015-06-29 23:12:39
【问题描述】:

好的,我有一个名为SpecialTilesList<SpecialTile>,其中SpecialTile 是一个结构。 SpecialTile 结构的属性之一是一个名为 Active 的公共布尔值,我正在尝试更改它,但由于某种原因它不起作用。我不确定它是否相关,但该列表由另一个类的实例拥有。这是我通过调试器运行时的图片:

所以无论如何,我遇到了这个问题,因为我最初尝试使用代码行

Mgen.SpecialTiles[ESV.editThis].Active = !Mgen.SpecialTiles[ESV.editThis].Active;

但它告诉我“活动”不是变量。如您所见,它不会让我以这种方式修改值:

所以我假设我必须通过一种方法修改值。但显然这也不起作用?

我是否遗漏了一些关于列表变量的内容?即使它不应该修改值,为什么调试器会将“活动”列为 false,然后将其翻转回 true?

谢谢!

【问题讨论】:

  • 你试过 mgen.SpecialTiles[ESV.editThis] = mgen.SpecialTiles[ESV.editThis].flipActive(); ?
  • 无论如何都支持问题标题:)
  • @MrPie 非常感谢,一旦我更改了 FlipActive 以返回更改后的结构值,它就可以正常工作。 ;)
  • @jjczopek 没有看到重复的,谢谢你的链接! :)

标签: c# list debugging reference


【解决方案1】:

这是结构的问题。调用列表索引器MGen.SpecialTiles[x] 返回存储在列表中的结构的副本,因此您在该结构上调用的任何方法都将对副本进行操作。而且由于副本是临时的,因此该方法所做的更改最终会被丢弃。

如果您将SpecialData 更改为一个类,这应该可以解决您的问题。

【讨论】:

  • 除非SpecialTiles 是一个数组。一些极端案例。
【解决方案2】:

这个变量并不顽固。您误解/没有注意到 structs 很特别。

结构是按值处理的,而不是按引用处理。

当你写作时:

foo.mystructList[5]

您指的是列表中的一个项目。但由于该 List 不包含对象 - 此索引返回您副本

考虑一下:

var temp = foo.mystructList[5]
temp.flip()

您现在希望'flip()' 起作用吗?请记住 List 包含结构。当然,您不会认为它起作用,因为您正在翻转副本。

现在回到你的案例:

foo.mystructList[5].flip()

同上!我只是消除了临时变量,但在里面,还是一样的。读取列表,返回副本,在副本上调用翻转。

这里:

foo.mystructList[5].prop = true

编译器拒绝“左手不是变量”,因为它知道左手是“副本”,很快就会消失。

这里:

foo.mystructList[5].flip()

编译器无法警告您:您正在对副本调用方法。会发生什么,取决于方法——如果它与结构配合得很好,它就会起作用。示例:

var area = foo.rectangles[5].calculatearea();   // =x*y, OK!
foo.rectangles[5].validate();  // throw when x<0 || y<0, OK!
foo.rectangles[5].draw(); // call some UI rendere with x,y,sizeX,sizeY, OK!

..但如果它试图改变结构,它仍然会成功,但在副本上。没有警告,因为它在所有情况下都是正确的 - 只是第一次看到时会感到惊讶。

举个有趣的例子,考虑“链接”:

struct Rect {
    ....
    public Rect twiceMe() {
        this.SizeX *= 2;
        this.SizeY *= 2;
        return this;
    }
}

foo.rectangles[5].twiceMe().draw();

这里,twoMe() 返回更改后的this,所以我可以“立即”调用draw。好像我在运行中将矩形乘以 2,然后在屏幕上以两倍的大小绘制它,但数组中不会有任何变化!

有效,但实际上,这些电话都不是真正即时的。上面的例子是这样的:

  • 从数组中读取第六项,返回该项(自动复制到这里
  • 在该副本上调用两次Me(),从中返回“this”(此处自动复制
  • 调用原始副本的放大副本

总结一下:不要过度使用结构体,或者非常了解它们,在修改它们时要格外小心。

【讨论】:

  • 总结一下:不要使用可变结构:)
  • @nawfal: true :) 我刚刚将所有“数组”编辑为“列表”,因为实际上,这是非常重要的一点。谢谢提醒,我要小心用词:)
  • 我知道结构是值类型(这实际上是我使用它们的原因,我希望能够轻松复制数据而不必担心引用)我只是认为对结构的引用仍然应该改变结构值。
猜你喜欢
  • 2018-10-29
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 2011-05-25
  • 2015-08-30
  • 2010-09-20
  • 1970-01-01
相关资源
最近更新 更多