2011-12-11 12 views
2

このcsharpコードを見て、リストから項目を見つけて削除した後にループを終了する必要がある理由を知ることができるかどうかを確認してください。foreachループでノードを削除する

internal void RemoveDirected(Node n) 
    { 
     foreach (EdgeToNeighbor etn in this.Neighbors) 
     { 
      if (etn.Neighbor.Key == n.Key) 
      { 
       RemoveDirected(etn); 
       break; 
      } 
     } 
    } 

    internal void RemoveDirected(EdgeToNeighbor e) 
    { 
     Neighbors.Remove(e); 
    } 

:アイデアは隣人のノードのリストを通過し、ノードnが存在するかどうかを確認し、その隣人を削除することです。 。 。

// Removes EdgeToNeighbor instance from AdjacencyList 
    protected internal virtual void Remove(EdgeToNeighbor e) 
    { 
     base.InnerList.Remove(e); 
    } 

私は最初の方法でRemoveDirected呼び出し後に「休憩」を持っているかに注意してください。 私は、RemoveDirectedの後に終了しないと、 がforeachループで永遠に続行されることがわかりました。私はそれが foreachが動作する方法と関係がなければならないと思います。 foreachが動作しているリスト を変更すると、混乱とループが永遠に起こります。

あなたはこのタイプのものを見たことがありますか?そして、breakを使用するのではなく、他のオプションは何ですか? もちろん、私が見つけたノードをローカル変数に置き、ループから外して、 ループ外でそれを削除することができます。しかし、私は思っていた、これを行うより良い方法があるかもしれない csharpで。

+0

フィードバックをお寄せいただきありがとうございます。私が作りたいのは、あなたが提案している解決策のコードを提供してください。コード例は、間違いなくあなたが推薦しているものをより明確にします。前もって感謝します。 –

答えて

0

ノードの数を取得して、forループの中で最も高いものから最も低いものをチェックして削除すると、もはや存在しないアイテムを探すことができなくなります。

+0

あなたが提案しているコードの例を提供できるなら、私は非常に感謝します。 –

+0

@FoRum下記のCompetent_techの答えを確認してください。 –

8

イテレータを使用して.NETコレクションを反復処理する場合は、そのコレクションを変更しないでください。もしそうしたら、あなたはトラブルを求めています。

foreachループで削除するのではなく、削除を延期する必要があります。たとえば、リスト内で削除する必要があるものすべてを収集してから、foreachの外に削除することができます。

var toDelete = this.Neighbors.Where(etn => etn.Neighbor.Key == n.Key).ToList(); 
foreach (var e in toDelete) { 
    Neighbors.Remove(e); 
} 
+0

これは愚かなようです...削除するもののリストを作成する場所:P〜 –

+0

@pstなぜですか?このコードは、それを読む人に意図を伝えます。なぜなら、それは普通の英語のように読めるからです。私にとっては、最適化を行うことで潜在的に節約できるCPUサイクル数を大幅に上回ります。 – dasblinkenlight

+0

Where *は*フィルターなので愚かなようです。他に副作用コードがあった場合は、そのアプローチを使用することもありますが、このようなケースではありません。(私はNeighborsが*共有されていないと推測していると思いますが、それはほとんど常に私のコードで有効なより大きな仮定です。) –

1

アイテムを削除する場合は、間違いなくイテレータを使用しないでください。 1つのオプションは、下向きにカウントループにそれを変更することです:

for (int nI = this.Neighbors.Count; nI >= 0; nI--) 
    { 
     var etn = this.Neighbors[nI]; 
     if (etn.Neighbor.Key == n.Key) 
     { 
      RemoveDirected(n); 
     } 
    } 

あなたはまた、ループ内でコレクションに削除するキーやアイテムを収集し、その後、あなたの反復を完了したら、削除を行うことができます。

ただし、1つのアイテムのみを削除していて、コレクションのアイテムが何らかの形でキー入力されている場合、実際にはループは必要ありません。コレクション内のキーまたはアイテムの存在をテストし、存在する場合は削除するだけです。

関連する問題