无法修改存储在另一个属性中的结构的属性

时间:2012-04-24 21:21:53

标签: c# .net

我有一点问题,我无法修改存储在另一个属性中的结构属性,我不明白为什么:

代码:

    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;

有效。有人可以向我解释一下吗?

2 个答案:

答案 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