1

これが可能かどうか、誰かが私にアドバイスしてもらえますか。XNA フレームワークの GameState に関する Microsoft のコード サンプルを見ています。クラスの 1 つで、「Public ReadOnly」配列データ メンバーを使用します。オブジェクト指向を促進する慣行ではありませんが、それは何も悪いことではありません。

クラスは後でコンストラクター内でインスタンス化しますが、これまでのところ非常に優れており、MSDN にも記載されています。

問題: クラスは後でクラス メソッド内の配列を反復処理し、配列内のデータを変更します。私はMSDNを見て、それをグーグルで検索しましたが、どこを見ても、エラーが発生するというフラットアウトと表示されています。読み取り専用配列の特別な例外はありますか?

お知らせ下さい。

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

読み取り専用配列の要素を変更してもまったく問題ありません。参照を再割り当てすることはできません。(CurrentKeyboardStates/LastKeyboardStates を新しい配列などに設定することはできません。) 要素の値は変更できます。

于 2012-07-22T22:30:24.467 に答える
1

他の 2 人のポスターが言及しているように、参照されているアイテムを変更しても問題はありません。読み取り専用の場合、参照自体を変更することはできません。

したがって、必要なのは変更可能な配列ではなく、一度定義すると変更できない他の構造です。完全な解決策を提供するつもりはありませんが、インターフェイスIEnumerableIEnumeratorインターフェイスを確認する必要があります: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx

于 2012-07-22T22:35:29.190 に答える
1

readonlyコンストラクターで設定された後は、変数を変更できないことを意味します。ただし、この場合、それは変更可能な配列オブジェクトへの参照です。

フィールドが値型 ( などint) の場合、理解は正しいです。フィールドは、初期化子または任意のコンストラクターによって設定できます。フィールドとほぼ同じですconst

しかし、それが参照である場合、保証できるのは、常に同じ objectを参照することだけです。そのオブジェクトを変更できるかどうかは、その実装次第です。したがって、配列の場合、配列の内容は変更できますが、長さなどは変更できません。

については、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 に答える