1

如果可能的话,有人可以告诉我。我正在查看 Microsoft 在 GameState 上为其 XNA 框架提供的代码示例。在其中一个类中,他们使用“Public ReadOnly”数组数据成员。虽然不是一种促进 OO 的做法,但这并没有错。

该类稍后在构造函数中实例化它,到目前为止一切都很好,它也记录在 MSDN 上。

问题:该类稍后在类方法中遍历数组并更改数组中的数据。我查看了 MSDN 并在其上进行了 Google 搜索,并且在我所看到的任何地方都说完全会出错。只读数组有特殊例外吗?

请指教。

public class InputState
{
    public readonly KeyboardState[] CurrentKeyboardStates;
    public readonly KeyboardState[] LastKeyboardStates;

    public InputState()
    {
        CurrentKeyboardStates = new KeyboardState[max];  
        LastKeyboardStates = new KeyboardState[max];  
    }
    //Does not make sense code...
    public void Update()
    {
        for (int i=0; i < max; ++i)
        {
            //this should throw errors...
            CurrentKeyboardStates[i] = LastKeyboardStates[i];  
            LastKeyboardStates[i] = Keyboard.GetState();
            //more code....
        }
    }
}
4

3 回答 3

1

readonly表示变量在构造函数中设置后不能更改。但是,在这种情况下,这是对数组对象的引用,可以更改。

如果字段是值类型(例如int),那么您的理解是正确的。该字段可以由初始化程序或任何构造函数设置。这与字段几乎相同const

但如果它是一个引用,那么我们只能保证它总是引用同一个对象。您是否可以修改该对象取决于其实现。因此,在数组的情况下,例如,您可以更改数组的内容,但不能更改其长度。

请参阅 MSDN 文档以获取readonly.

SLaks指出此警告将从代码分析中生成:CA2105: Array fields should not be read only。你在这里提出来就是为了这个目的。标记数组readonly会给您一种无法修改的错误安全感。但是,您唯一不能做的就是为该字段分配不同的数组。


如果您想将一组信息暴露给外部,而不会被更改,那么最好的方法是使用IEnumerable<T>属性:

public class Foo {
    private int[] _data = new int[40];

    public IEnumerable<int> Data {
        get { return _data; }
    }
}

这将允许该类的使用者对其进行迭代,就像任何其他IEnumerable

Foo f = new Foo();
foreach (int d in f.Data) {
    //...
}

f.Data[0] = 7;           // This won't work. IEnumerable doesn't have [] operator.
f.Data = new int[10];    // This won't work. Data only has a getter.
于 2012-07-22T22:28:36.723 回答
1

更改只读数组的元素非常好,只是不能重新分配引用。(不能将 CurrentKeyboardStates/LastKeyboardStates 设置为新数组等)可以更改元素值。

于 2012-07-22T22:30:24.467 回答
1

就像其他两张海报提到的那样,更改被引用的项目并没有错。当它是只读的时,您不能更改引用本身。

所以你想要的不是一个可修改的数组,而是其他一些一旦定义就不可修改的结构。我不会给你一个完整的解决方案,但你应该查看IEnumerableIEnumerator接口:http: //msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx

于 2012-07-22T22:35:29.190 回答