2

独自のプロパティ(位置、速度など)を持つパーティクルと呼ばれるオブジェクトがあり、ウィンドウフォームでパーティクルのリストを作成します。次に、このパーティクルのリストがコードで更新されます(つまり、各パーティクルの位置、速度などが各反復ステップで更新されます)。

私がやりたいのは、これList<Particle>を反復ごとに別のリストに追加してList<List<Particle>>(ボタンをクリックした後)、比較できる粒子の個別のリストを作成できるようにすることです。

これは私のコードがどのように見えるかです(UpdateEngineは、初期化メソッドでパーティクルのリストを作成し、リスト内のパーティクルの値を更新する他のメソッドを持っているクラスです):

public partial class frmMain : Form
{
    private List<List<Particle>> listPlist;

    private UpdateEngine Engine;

    ...

    public frmMain()
    {
        InitializeComponent();

        listPlist = new List<List<Particle>>();

        Engine = new UpdateEngine();
    }

    ...

    //pressing this button iterates through a specified number of iterations
    private void btPrep_Click(object sender, EventArgs e)
    {            
        //create the particles and add the first list to the list of lists
        Engine.Initialize();
        listPlist.Add(Engine.ParticleList);

        //iterate through the list of particles in Engine and update their properties
        for(i = 0; i <= iterations; i++)
        {
            Engine.Update();
            listPlist.Add(Engine.ParticleList);
        }
    }
}

私が起こっているのは、反復がうまくいく前に最初のリストが追加されていることです。forループに追加された最初のリストは正常に追加されます。その後に追加されたすべてのリストは、listPlist内のすべてのリストを現在のリストと同一になるように変更します。

コードを実行したときに表示される例:

初期化後:

  • listPlist(0)> Particle(0)> Position = 0,0

最初の反復後:

  • listPlist(0)> Particle(0)> Position = 0,0
  • listPlist(1)> Particle(0)> Position = 1,1

次の反復後:

  • listPlist(0)> Particle(0)> Position = 2,2
  • listPlist(1)> Particle(0)> Position = 2,2
  • listPlist(2)> Particle(0)> Position = 2,2

これを修正する方法がよくわかりません。なぜこれが起こっているのか誰かが知っていますか?

4

3 に答える 3

3

あなたの質問から私が理解していることから、問題はあなたが参照アイテムのコピーを作成しようとしているということです。それがすべてのリストアイテムが変化しているのを見る理由です。

これらのリスト/パーティクルのディープクローンを作成して、参照に依存しないようにする必要があります。

これを実現するには、パーティクルオブジェクトに新しいコピーメソッドまたはコンストラクタを追加する必要がある場合があります。

何かのようなもの

public class Particle
{
    public int SomeField;

    public Particle Copy()
    {
        return new Particle { SomeField = this.SomeField };
    }   

    public Particle(Particle copyFrom)
    {
        this.SomeField = copyFrom.SomeField;
    }
}

次に、元のリストのコピーを次のように作成できます。

List<Particle> copyList = new List<Particle>(originalList.Select(c => c.Copy));
于 2012-07-25T04:34:21.220 に答える
0

答えは本当に何をするかに依存Engine.Updateします。を更新しParticleListて新しいParticle値を入力する場合は、ループの内側と外側で次の変更を行うことができます(リストをコピーします)。

listPlist.Add(new List<ParticleList>(Engine.ParticleList));

ただしEngine.Update、同じオブジェクトの内部値を更新するだけの場合は、他の人が述べているようParticleに、リストと内部のオブジェクトをコピーして、ディープコピーを作成する必要があります。Particle

于 2012-07-25T04:48:34.207 に答える
0

あなたが遭遇しているのは、List<>オブジェクトが下にあるオブジェクトのみを指しているためParticleです。同じパーティクルが2つ(またはそれ以上)の異なるリストにあり、1つのリストからパーティクルにアクセスしているか、他のリストからパーティクルにアクセスしているかに関係なく、変更されたオブジェクトを指している場合。「ボブ・スミス」は電話帳に載っていて、家にも住んでいると言っているようなものです。ボブの家に行って足を切ったとしましょう。ボブに電話すると(同じ方法で彼にアクセスするのではなく)、ボブにはまだ両方の足がありません。

@astanderが言ったように、Particleクラスにメソッドを作成して、オブジェクトのディープクローンと呼ばれるものを作成できます。このメソッドは、ほとんどの場合、元のオブジェクトのすべてのプロパティ(およびフィールド)を新しいオブジェクトにコピーします。ただし、注意する必要があります。aParticleにタイプSubParticle(またはその他のオブジェクト)のフィールドがある場合、ディープクローンを作成するときは、そのオブジェクトのディープクローンも実行する必要があります。それ以外の場合は、2つParticleのs(元のオブジェクトとコピー)を作成します。 )は両方とも同じを指しSubParticleます。

また、特定のコンテキストでは、ループを繰り返すたびに、パーティクルコピーの新しいリストを作成することをお勧めします。その後、リストからパーティクルを削除すると、GarbageCollector参照されなくなった場合にそのパーティクルが処理されます。

編集:コードを読み直すことで、次の結論に達しました。Engine.Update()メソッドで、コピーの新しいリストを作成することから始めることができます。これは、Engine.Update()を呼び出すたびに、パーティクルが同じオブジェクトではないことを意味します。これを行うには、最初にディープクローンを返すParticle.Copy()メソッドを実装し、次のようにしてEngine.Update()を起動します。

ParticleList = new List<Particle>(ParticleList.Select(p=>p.Copy()));
于 2012-07-25T04:50:31.530 に答える