为结构索引器

时间:2016-07-24 19:22:48

标签: c# indexing struct

我收到编译错误'无法修改表达式,因为它不是变量'。我理解一个人不能为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.

如果我将访问者类型更改为类,则一切正常,但即使复制了结构,对相关数组的引用仍然有效吗?或者这种情况下的错误只是因为我正在做一些我不应该做的事情,而不是一个实际的错误?

2 个答案:

答案 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

  

发生此错误是因为在分配时复制了值类型。什么时候   您正在从属性或索引器中检索值类型   对象的副本,而不是对象本身的引用。副本   返回的内容不会由属性或索引器存储,因为它们   实际上是方法,而不是存储位置(变量)。你必须   将副本存储到您可以修改之前声明的变量中   它

     

如果要定义类或结构,则可以通过以下方式解决此错误   修改您的属性声明以提供对成员的访问权限   一个结构。如果您正在编写客户端代码,则可以解决该错误   通过创建自己的结构实例,修改其字段,和   然后将整个结构分配回属性。作为第三个   或者,您可以将结构更改为类。