为字典中的结构赋值时发生编译错误

本文关键字:编译 错误 赋值 字典 结构 | 更新日期: 2023-09-27 18:08:53

各位,我在下一个代码中遇到编译错误("不能修改字典的返回值,因为它不是变量"(:

public class BaseForm : Form
{
    protected void StoreGridViewPosition(DataGridView grid)
    {
        if (grids.ContainsKey(grid))
        {
            grids[grid].RowIndex = grid.CurrentCell.RowIndex;
            grids[grid].ColumnIndex = grid.CurrentCell.ColumnIndex;
        }
        Cell s = new Cell();
        s.RowIndex = 213;
    }
    protected void LoadGridViewPosition(DataGridView grid)
    {
    }
    private Dictionary<DataGridView, Cell> grids = new Dictionary<DataGridView, Cell>();
    private struct Cell
    {
        public int RowIndex;
        public int ColumnIndex;
    }
}

但如果我将struct(Cell(替换为class,那么它就可以正常工作。为什么会发生这种情况?

为字典中的结构赋值时发生编译错误

这不会像您预期的那样工作。当你打电话时:

grids[grid].

结构的副本是从索引器返回的,而不是引用。所以当你进入它时:

grids[grid].RowIndex = grid.CurrentCell.RowIndex;

您实际上是在设置结构的副本。然后立即丢弃此副本。所有这些行为都源于structs的值类型语义。

如果你使用一个结构,你所能做的就是在单元格中设置一个全新的结构:

grids[grid] = new Cell { RowIndex = 3, ColumnIndex = 1 };

或者提取旧结构的副本并将其放回(暂时忽略结构应该始终保持不变(:

var cell = grids[grid];
cell.RowIndex = 3;
grids[grid] = cell;

将定义更改为类意味着索引器返回该类的引用,当您的引用和字典的引用都指向同一个底层对象时,您可以对其进行更改。

编译器(用不太多的词(说,你无意中试图更改你认为正在更改的内容的副本如果你将一个结构作为类的属性公开,并试图对结构成员进行变异,那么你很容易犯同样的错误:

myClass.MyPointStruct.X = 2;

(这似乎在新编译器中给出了相同的错误消息,至少,我可以发誓它曾经让你这样做…(

或者,如果将结构强制转换为接口,则将副本装箱。

这个问题非常相似:

修改字典中的结构变量

当StoreGridViewPosition调用Cell时,您会在其中获得结构的副本。您的调用会更新值,然后将其丢弃(即没有任何有用的东西(。

构造一个值类型,因此当来自字典时,您得到的是字典中的值的副本。C#实际上是在防止你有坏的惊喜