2

私が構造体を持っていると仮定します:

struct Vector
{
    public int X, Y;

    // ...
    // some other stuff
}

とクラス:

class Map
{
    public Vector this[int i]
    {
        get
        {
            return elements[i];
        }
        set
        {
            elements[i] = value;
        }
    }

    private Vector[] elements

    // ...
    // some other stuff
}

次のようなことができるようにしたいと思いますmap[index].X = 0;が、戻り値が変数ではないため、できません。

可能であれば、どうすればよいですか?

4

4 に答える 4

4

可変構造体は避けてください。

タイプを変更可能にする場合は、代わりにクラスを使用してください。

class Vector
{
    public int X { get; set; } // Use public properties instead of public fields!
    public int Y { get; set; }

    // ...
    // some other stuff
}

構造体を使用する場合は、不変にします。

struct Vector
{
    private readonly int x;  // Immutable types should have readonly fields.
    private readonly int y;

    public int X { get { return x; }} // No setter.
    public int Y { get { return y; }}

    // ...
    // some other stuff
}
于 2012-05-15T20:09:14.560 に答える
3

インデクサーは参照ではなくオブジェクトのコピーを返すため、コンパイラーはこれを実行できません(構造体は値によって渡されます)。インデクサーはコピーを返します。このコピーを変更しても、結果は表示されません。コンパイラーは、この状況を回避するのに役立ちます。

このような状況を処理したい場合は、代わりにクラスを使用するか、Vectorの処理方法を変更する必要があります。値を変更するのではなく、コンストラクターで値を初期化する必要があります。このトピックの詳細:可変構造体が「悪」であるのはなぜですか。

于 2012-05-15T20:11:16.540 に答える
1
  • ベクターをクラスとして定義する、または
  • 値を一時変数に格納します

    var v = map [index]; vX = 0; map [index] = v;

また

  • map [index] = map [index] .Offset()を変更する関数を追加します

また

  • []演算子がセッタークラスを返すようにします

    クラスセッター{Vector[]データ; intインデックス; public double X {get {return Data [Index]; } set {Data [Index] = new Vector(value、Data [Index] .Y); }}}

    public Setter this [int i] {get {return new Setter(){Data = elements、Index = i}; }}

于 2012-05-15T20:09:25.827 に答える
1

ジェネリッククラスは多くの目的で非常にうまく機能しますが、参照によって構造体にアクセスするための合理的な方法を提供していません。多くの場合、構造体のコレクションは、クラスオブジェクトのコレクションよりも優れたパフォーマンス(メモリフットプリントの削減とキャッシュの局所性の向上の両方)と明確なセマンティクスを提供するため、これは残念なことです。構造体の配列を使用する場合、非常に明確な効果を持つようなステートメントを使用できます。のフィールドはArrayOfRectangle[5].Width += 3;更新されますが、タイプの他の格納場所のフィールドには影響しません。それを確実にするために知っておく必要があるのは、それがであり、パブリックフィールドを持つ構造体であるということだけです。クラスであり、インスタンスが保持されている場合XArrayOfRectangle[5]XRectangleArrayOfRectangleRectangle[]RectangleintXRectangleArrayOfRectangle[5]これまで外界にさらされたことがある場合、によって参照されるインスタンスが、そのインスタンスのArrayOfRectangle[5]フィールドが変更されないことを期待していた他のコードによっても保持されているかどうかを判断するのは困難または不可能である可能性がXあります。構造を使用すると、このような問題は回避されます。

.netのコレクションの実装方法を考えると、通常、構造体のコピーを作成して変更し、保存するのが最善の方法です。これを行うのはやや厄介ですが、それほど大きくない構造体の場合、値型を使用することで達成されるメモリフットプリントとキャッシュの局所性の向上は、データ構造との間でオブジェクトを明示的にコピーするための余分なコードを上回る可能性があります。不変のクラス型を使用する場合と比較して、ほぼ確実に大きな勝利になります。

ちなみに、私が見たいのは、コレクションが次のようなメソッドを公開することです。 これは、渡されたパラメーターとともにコレクションの適切な要素をOperateOnElement<paramType>(int index, ref T element, ref paramType param, ActionByRef<T,paramType> proc)呼び出します。procこのようなルーチンは、多くの場合、クロージャを作成せずに呼び出すことができます。このようなパターンが標準化されていれば、コンパイラーはそれを使用してフィールド更新コードを適切に自動生成することもできます。

于 2012-05-16T00:26:28.373 に答える