让我们假设以下情况:
struct MyStruct {
public SomeClass? someObject;
public SomeClass? SomeObject { get => someObject; set => someObject= value;}
public void SetObject(SomeClass someObject) => this.someObject = someObject;
}
如果我们得到一个结构体,例如通过实现 this[] 来使用 get(例如,最简单的实现:MyStruct this[int i]{get => arr[i]; set => arr[i] = value;}
),那么出于显而易见的原因,我们无法更改MyStruct.someObject
。然而,该方法MyStruct.SetObject(obj)
不会抛出错误,这不能说MyStruct.SomeObject = obj
,尽管事实上它们执行相同的代码。你能解释一下为什么 setter 不起作用但方法却起作用吗?
一般来说,使用数组 ( MyStruct[] array
) 我们可以更改结构体 ( ) 的字段array[0].someObject = ...
。如何在对象中实现此类功能?
编辑:根据要求附加示例代码:
class CellData {public int param;} // Его можно переопределять
struct CellContainer{
/* тут всякие другие поля */
public CellData? cellData;
public CellData? CellData {get => cellData; set => cellData = value;}
public void SetCellData(CellData? cellData) => this.cellData = cellData;
}
class Grid{
CellContainer[,] grid;
public CellContainer this[Vector2 pos]
{
get => grid[pos.x, pos.y];
set => grid[pos.x, pos.y] = value;
}
}
Grid grid = …;
grid[pos].cellData = …; // Не работает
grid[pos].CellData = …; // Тоже не работает
grid[pos].SetCellData(…); // Не вызывает ошибок
虽然从理论上讲,SetObject
它不应该改变原始对象,而只能改变它的副本......如果我们不将它存储在堆栈上,它到底存储在哪里
这里的要点是结构是按值传递的。
看,当您访问结构类型的属性时,这就是幕后发生的事情:
也就是说,首先复制结构,然后尝试用此副本更改某些内容。
由于此操作完全没有意义,因此编译器不允许您直接对字段和属性进行赋值。但编译器允许您调用该方法 - 因为它不知道该方法到底做什么。
如何解决这个问题?嗯,有两个选择。对于初学者,您可以删除该结构并将 CellContainer 设为一个类。
此外,在该语言的现代版本中,您可以返回对结构的引用: