C# 向字典中的结构赋值时出现编译错误
各位, 我在下一个代码中遇到编译错误(“无法修改dictionary的返回值,因为它不是变量”):C# 向字典中的结构赋值时出现编译错误,c#,winforms,class,struct,C#,Winforms,Class,Struct,各位, 我在下一个代码中遇到编译错误(“无法修改dictionary的返回值,因为它不是变量”): public class BaseForm : Form { protected void StoreGridViewPosition(DataGridView grid) { if (grids.ContainsKey(grid)) { grids[grid].RowIndex = grid.CurrentCell.Ro
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;
}
}
公共类基表单:表单
{
受保护的void StoreGridViewPosition(DataGridView网格)
{
if(网格。容器(网格))
{
grids[grid].RowIndex=grid.CurrentCell.RowIndex;
grids[grid].ColumnIndex=grid.CurrentCell.ColumnIndex;
}
单元s=新单元();
s、 行指数=213;
}
受保护的无效LoadGridViewPosition(DataGridView网格)
{
}
私有字典网格=新字典();
专用结构单元
{
公共综合指数;
公共指数;
}
}
但如果我用类替换结构(单元),那么它就可以正常工作。
为什么会发生这种情况?这不会像您预期的那样起作用。当你打电话时:
网格[网格]。
从索引器返回结构的副本,而不是引用。因此,当你开始时:
grids[grid].RowIndex=grid.CurrentCell.RowIndex代码>
实际上,您正在设置结构的副本。然后立即丢弃该副本。所有这些行为都源于结构的值类型语义
如果使用结构,则可以在单元格中设置一个全新的结构:
grids[grid]=新单元格{RowIndex=3,ColumnIndex=1}代码>
或者拉一个旧结构的副本并将其放回(暂时忽略结构确实应该始终保持不可变的:-):
将定义更改为类意味着索引器返回对该类的引用,当引用和字典的引用都指向同一基础对象时,可以对该类进行变异
编译器说(不是用太多的话)您无意中试图更改您认为正在更改的内容的副本。如果将结构作为类的属性公开,并尝试对结构成员进行变异,则很容易犯同样的错误:
myClass.MyPointStruct.X=2代码>
(这似乎在新的编译器中给出了相同的错误消息,至少,我可以发誓它曾经允许您这样做……)
或者,如果将结构强制转换为接口,则装箱一个副本
这个问题非常相似:
这不会像您预期的那样起作用。当你打电话时:
网格[网格]。
从索引器返回结构的副本,而不是引用。因此,当你开始时:
grids[grid].RowIndex=grid.CurrentCell.RowIndex代码>
实际上,您正在设置结构的副本。然后立即丢弃该副本。所有这些行为都源于结构的值类型语义
如果使用结构,则可以在单元格中设置一个全新的结构:
grids[grid]=新单元格{RowIndex=3,ColumnIndex=1}代码>
或者拉一个旧结构的副本并将其放回(暂时忽略结构确实应该始终保持不可变的:-):
将定义更改为类意味着索引器返回对该类的引用,当引用和字典的引用都指向同一基础对象时,可以对该类进行变异
编译器说(不是用太多的话)您无意中试图更改您认为正在更改的内容的副本。如果将结构作为类的属性公开,并尝试对结构成员进行变异,则很容易犯同样的错误:
myClass.MyPointStruct.X=2代码>
(这似乎在新的编译器中给出了相同的错误消息,至少,我可以发誓它曾经允许您这样做……)
或者,如果将结构强制转换为接口,则装箱一个副本
这个问题非常相似:
构造一个值类型,因此当你从字典中得到一个值时,你得到的是字典中的值的副本。C#实际上是在阻止你有坏习惯
惊喜…构造一个值类型,这样当你从字典中得到的是字典中的值的副本。C#实际上是在阻止你有坏习惯
惊喜…当你的StoreGridViewPosition调用你的单元格时,你会得到里面结构的副本。您的呼叫会更新该值,然后将其丢弃(即没有任何有用的内容) 当你的StoreGridViewPosition调用你的单元格时,你会得到里面结构的副本。您的呼叫会更新该值,然后将其丢弃(即没有任何有用的内容)
var cell = grids[grid];
cell.RowIndex = 3;
grids[grid] = cell;