3

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

代码:

    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;

有用。谁能给我解释一下?

4

2 回答 2

7

Astruct是一种值类型,因此当您从属性访问它时,您将返回一个副本struct而不是底层字段直接。因此,C# 不允许您修改该结构的副本,因为这只是一个将被丢弃的临时对象。

所以,当你打电话时:

BNDTitleInfo.NavigovatNa = ...;

它首先调用get属性并返回 的副本bndTitleInfo,然后尝试设置NavigovatNa属性和副本。C# 在这里给您错误,因为这不是您真正想做的事情,因此可以保护您免受自己的伤害。

但是,当你打电话时:

bndTitleInfo.NavigovatNa = ...;

您直接引用该字段,因此没有复制,也没有编译器问题。

总而言之,可变值类型不能产生好的属性(通常你应该完全避免可变值类型)。

要进行纠正,您可以将其设为引用类型 ( class),也可以将struct其设为不可变,这意味着您必须分配一个全新的 struct 实例来更改它的值。

如果您查看 MSDN 的建议,通常struct最适合小型、逻辑单值、不可变结构:在类和结构之间选择

于 2012-04-24T21:27:11.413 回答
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% 的把握它不应该是 a InfoProTile

BNDTileInfoa class,除非你能非常清楚地解释为什么它是 a struct然后可以证明它为什么是mutable struct

于 2012-04-24T21:28:18.073 回答