2016-07-24 19 views
1

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

如果我改变我的访问类型,以一流的这一切工作正常,但肯定即使该结构被复制参考相关数组仍然有效?或者这种情况下的错误仅仅是因为我正在做我不应该做的事情,而不是实际的错误?

回答

1

"I understand that one cannot assign a value to a struct property because a copy of a struct is returned, but I don't think that applies in this case."

诚然,在这种情况下,它不会导致它通常会导致错误。
但编译器根本不允许它,因为这个写入一个结构的副本很可能导致错误。

错误消息包含了解决方案:

Cannot modify a value type return value of `DualArray.A'. Consider storing the value in a temporary variable.

所以,它存储在一个变量:

var a = dual.A; 
a[5] = 2; 
+0

谢谢,我想这可能是一个伪装成错误的警告,因为它是如此严重。可惜的是,这种解决方案破坏了拥有一个命名访问者的好处。我现在将Accessor 更改为引用类型,这使我可以保持简洁的分配。 –

+1

@DavidRutten:这不是“伪装成错误的警告” - 这是一个错误。表达式'dual.A'被分类为一个值,而不是一个变量。因此你不能使用索引器设置器。任何*做*的编译器都会违反语言规范。 –

+0

@JonSkeet,我知道,这是一个错误,因为它被定义为这样,而不是因为它实际上是荒谬的。我足够理解,我明白为什么规格设计师认为将这种危险代码扼杀在萌芽状态是非常重要的。 –

0

你可以这样做:

DualArray<int, bool> dual = new DualArray<int, bool>(); 
var acc = dual.A; 
acc[5] = 2; 

最初的设计错误是由于价值型直接(从方法返回)特性,这可能会导致意想不到的结果的变化,因为这是指的副本价值型。但在你的情况下,因为你在引用类型中混合了值类型,通过存储你在类中构造struct的后备数组,所以你不会得到意想不到的结果。

从错误docs

This error occurs because value types are copied on assignment. When you retrieve a value type from a property or indexer, you are getting a copy of the object, not a reference to the object itself. The copy that is returned is not stored by the property or indexer because they are actually methods, not storage locations (variables). You must store the copy into a variable that you declare before you can modify it.

If you are defining the class or struct, you can resolve this error by modifying your property declaration to provide access to the members of a struct. If you are writing client code, you can resolve the error by creating your own instance of the struct, modifying its fields, and then assigning the entire struct back to the property. As a third alternative, you can change your struct to a class.

+0

但没有什么对我的价值型改变,它代表一切回到阵列它包装和数组是引用类型。 –

+0

对编辑的回应:我在什么时候给A赋值? –

+0

@DavidRutten'dual.A'返回结构体的一个副本。 – user3185569