我有一点问题,我无法修改存储在另一个属性中的结构属性,我不明白为什么:
代码:
public struct InfoProTile
{
public string Nazev { get; set; }
public double Hodnota { get; set; }
public TypValue TypValue { get; set; }
public NavigovatNa NavigovatNa { get; set; }
}
public InfoProTile BNDTileInfo { get { return bndTileInfo; } set { bndTileInfo = value; } } private InfoProTile bndTileInfo;
LoadModel()
{
...
BNDTileInfo = new InfoProTile();
BNDTileInfo.NavigovatNa = NavigovatNa.MainPage;
}
错误:
Error: Error 3 Cannot modify the return value of '...ViewModel.TilesModel.BNDTileInfo' because it is not a variable
我不明白因为如果我把它改成:
bndTileInfo.NavigovatNa = NavigovatNa.MainPage;
有效。有人可以向我解释一下吗?
答案 0 :(得分:7)
struct
是一种值类型,因此当您从属性访问它时,您将获得struct
的副本,而不是基础字段direclty。因此,C#将不允许您修改结构的副本,因为它只是一个将被丢弃的临时对象。
所以,当你打电话:
BNDTitleInfo.NavigovatNa = ...;
首先调用属性上的get
并返回bndTitleInfo
的副本,然后尝试设置NavigovatNa
属性和副本。 C#在这里给出了错误,因为这不是你真正想做的事情,因此可以保护你自己。
但是,当你打电话时:
bndTitleInfo.NavigovatNa = ...;
您正在直接引用该字段,因此不会进行复制,也没有编译器问题。
它的长期和短期是可变值类型不能产生好的属性(通常你应该完全避免使用可变值类型)。
要纠正,您可以将其设为引用类型(class
),也可以使struct
不可变,这意味着您必须分配一个全新的结构实例来更改它值。
如果你看一下MSDN的建议,一般struct
最适合小的,逻辑单值,不可变的结构:Choosing Between Classes and Structures
答案 1 :(得分:7)
由于BNDTileInfo
是一个属性,因此您可以获得数据的克隆。当克隆被丢弃时,对克隆的更改将丢失,即您的代码为:
var tmp = BNDTileInfo; // tmp is a completely separate clone
tmp.NavigovatNa = NavigovatNa.MainPage; // change the local clone
// discard the clone - our change was wasted
编译器阻止了你遇到大问题。这是因为struct
意味着,即值类型语义,即复制语义。
这里的真正答案是:不要将其作为struct
。即使不知道这些词是什么,我99%肯定不应该是struct
。当然,即使您刚刚说“我有struct
名为struct
”,我仍然有98.5%确定它不应该是InfoProTile
。
让BNDTileInfo
成为class
,除非你能解释非常清楚为什么它是struct
,和可以证明是正确的为什么它是 mutable struct
。