我收到编译错误'无法修改表达式,因为它不是变量'。我理解一个人不能为struct属性赋值,因为返回了一个struct的副本,但我不认为这适用于这种情况。
我有一个DualArray类,其目的是保持两个数组同步。我想使用A属性访问'first'数组中的项目,使用B属性访问'second'数组中的项目。这些属性将具有索引器的结构返回到相应的数组中。
public struct Accessor<T>
{
private readonly T[] _array;
public Accessor(T[] array)
{ _array = array; }
public T this[int index]
{
get { return _array[index]; }
set { _array[index] = value; }
}
}
/// <summary>
/// Maintains two arrays.
/// </summary>
public class DualArray<T1, T2>
{
// ...
public Accessor<T1> A
{
get { return new Accessor<T1>(_arrayT1); }
}
public Accessor<T2> B
{
get { return new Accessor<T2>(_arrayT2); }
}
// ...
}
现在,当我尝试使用此代码时,我收到错误:
DualArray<int, bool> dual = new DualArray<int, bool>();
// ...
dual.A[5] = 2; // <-- sad trombone.
如果我将访问者类型更改为类,则一切正常,但即使复制了结构,对相关数组的引用仍然有效吗?或者这种情况下的错误只是因为我正在做一些我不应该做的事情,而不是一个实际的错误?
答案 0 :(得分:1)
“我知道无法为结构属性赋值 因为返回了一个结构的副本,但我不认为这适用 在这种情况下。“
是的,在这种情况下,它不会导致它通常导致的错误 但是编译器根本不允许它,因为这种写入-a-copy-a-struct有很大的潜在错误。
错误消息包含解决方案:
无法修改`DualArray.A'的值类型返回值。 考虑将值存储在临时变量中。
因此,将其存储在变量中:
var a = dual.A;
a[5] = 2;
答案 1 :(得分:0)
你可以这样做:
DualArray<int, bool> dual = new DualArray<int, bool>();
var acc = dual.A;
acc[5] = 2;
原始设计错误是由于更改了值类型(从方法返回)属性直接导致意外结果,因为它引用了value-type的副本。但是在你的情况下,因为你通过存储在类中构造结构的后备数组,在引用类型中混合值类型,所以你不会得到意想不到的结果。
错误docs:
发生此错误是因为在分配时复制了值类型。什么时候 您正在从属性或索引器中检索值类型 对象的副本,而不是对象本身的引用。副本 返回的内容不会由属性或索引器存储,因为它们 实际上是方法,而不是存储位置(变量)。你必须 将副本存储到您可以修改之前声明的变量中 它
如果要定义类或结构,则可以通过以下方式解决此错误 修改您的属性声明以提供对成员的访问权限 一个结构。如果您正在编写客户端代码,则可以解决该错误 通过创建自己的结构实例,修改其字段,和 然后将整个结构分配回属性。作为第三个 或者,您可以将结构更改为类。