• ベストアンサー

For Each文内でのコレクションの変更について

VB.Net/C# .NET Framework2.0で開発しております。 下記コード例のように、イテレータループ内(For Each文)でのコレクションの変更(要素の削除)ができないため、苦肉の策として下のように削除する予定のものを格納するバッファ(removeList)に一度登録し、その後もう一度ループをまわして実際に削除する、というコードを書いておりますが、分量も多くなり、一時変数なども出てくるため、あまりよいコードとは言えないと思います。 コレクションから特定の条件を満たした要素を削除するための、もうすこしスマートな書き方はないものでしょうか? 宜しくお願いいたします。 Dim removeList as new List(Of TestClass) For Each e as TestClass in targetList If e.IsDummy Then '直接targetList.Remove(o) とはできない removeList.Add(o) End If End For For Each e as TestClass in removeList targetList.Remove(e) End For

  • i_110
  • お礼率60% (28/46)

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

List(Of T)のRemoveAllで削除したほうがいいかもしれませんよ ' 削除条件を決定する関数を準備 Private Function myCheck( obj as TestClass) as Boolean   return obj.IsDummy End Function 呼び出し方 targetList.RemoveAll( AddressOf myCheck ) といった具合にしてやれば IsDummyがTrueになっているアイテムをすべて削除してくれますよ

i_110
質問者

お礼

あなた様は本当に神様か何かだと思います。本当にありがとうございました。本当に感謝しています。重ね重ね本当にありがとうございました。

その他の回答 (1)

  • yamada404
  • ベストアンサー率56% (9/16)
回答No.1

意図されている事かどうか分かりませんが。。 これでどうですか For i As Integer = 0 To targetList.Count - 1 Dim cls As TestClass = targetList(i) If cls Is Nothing Then Continue For End If If cls.IsDummy Then targetList.Remove(cls) End If Next

i_110
質問者

補足

ご回答ありがとうございます。 確かにこの方法でもできそうですね。一点、普段コレクションの走査でインデックスループをあまり用いないので、targetListからリアルタイムにRemoveしてしまった後の歯抜けリストの走査は正常に動作するのか不安があります(インデックスがずれたり等)。後で検証してみます。 その他、なるべくならFor Eachループを用いて簡潔な記法で書きたいと考えておりますので、他の方法もありましたら宜しくお願い致します。

関連するQ&A

  • for each で扱えるコレクションの実装

    こんにちは。 プログラムの保守を請け負っているのですが、独自に実装されているリストクラスがありまして、 それをfor eachで操作できるようにとの指示がありました。 処理系はC++です。 CFooArrayというクラスだとしまして、内部にCFooDataというクラスをdequeで持っています。 要望としては CFooArray arrayFoo ; for each( CFooData fooData in arrayFoo ) { } とできるようにしてほしいとのことですが、そもそもfor eachで扱えるコレクションクラスを どう実装していいのかが分かりません。またdequeを外に出すのはナシと言われました。 どなたかご存じの方がいらっしゃいましたら教えていただけないでしょうか。 参考サイトでも紹介していただければ幸いです。

  • アクセス For Eachの時点 絞る

    For Eachの時点で、コマンドボタンのみに絞ることは可能ですか? Sub Sample() Dim myFormName As String Dim ctl As Control myFormName = "フォーム1" For Each ctl In Forms(myFormName).Controls Debug.Print ctl.Name Next ctl End Sub これでフォーム上の全てのコントロール名を取得できますが ループの時点でコマンドボタンのみを抽出できますか? For Each ctl In Forms(myFormName).Controls If ctl.ControlType = acCommandButton Then Debug.Print ctl.Name End If Next ctl こうすれば、コマンドボタンのみ絞れますが コントロールの数が多すぎて、処理に時間がかかります。 なので For Each ctl In Forms(myFormName).Controls の部分の、ループの時点でコマンドボタンを絞りたいのですが 絞れる方法があれば教えてください。

  • ユーザーフォーム上でFor Each~Next?

    Excelユーザーフォームでマルチページを使用しているのですが テキストボックスに文字(パスワード的なもの)を入力したら マルチページ内の特定ページのコントロールをenabled=trueにしたいのです(通常はenebledがtrue・falseの混合ページです) 先日よりFor Each~Next構文を使い始めたのですが勉強不足『オブジェクト・コレクション』の概念がいまいち理解できません。よろしくお願いします。 ネット上で調べてコピペしたのですがこのままだと他のページ、ページ外のコントロールまで影響するので良い方法をアドバイスしていただけますか?やはりコントロール個別にコードを書くしかないのでしょうか? Private Sub TextPASS_Change() If TextPASS.Value = "aaaa" Then For Each Control In Controls 省略(enabled=true) Next Else For Each Control In Controls 省略(enabled=false) Next End If End Sub

  • セルに対してFor Each~In~Nextを使う

    セルに対してFor Each~In~Nextを使う事は出来ない? シートやブックに対してループする時は Sub aaa() Dim w As Worksheet For Each w In Worksheets MsgBox w.Name Next End Sub 等を使いますが、 A1に「あ」 A2に「い」 A3に「う」 が入っている場合、 Sub bbb() Dim i As Long For i = 1 To Range("a65536").End(xlUp).Row MsgBox Cells(i, 1) Next End Sub で、全ての値を取得できますが、 For~to~nextではなく セルに対してFor Each~In~Nextを使う方法があれば教えてください。 上記のように Dim w As Worksheetは宣言できますが Dim c As Workcellとはできませんでした。 なぜわざわざFor~to~nextでできる事をFor Each~In~Nextでやりたいかと言うと、 シートやブックはFor~to~nextでできるのに、セルはFor~to~nextができない理由を知りたいからです。 ご回答よろしくお願いします。

  • 構造体配列の特定のメンバーをFor~Eachで

    みなさんこんにちは。昔Vb6を少々やっていましたが ここ数年遠のいていました。 必要に迫られ最近Vb2010を勉強しはじめた50歳です。 サンプルの通り3つのメンバーを持つ構造体配列があり、 メンバーData3の合計を得るのに、ループで回して 計算してましたが、これを For~Next ではなくFor~Each で やれないかと考えておりました。配列の要素の個数が不定 な場合に便利だと思ったからです。 サンプルの ???_1が「型」で ???_2が「コレクション」と なるように記述するのだということまではわかりますが、 具体的な記述がわかりません。For~NetでもDo~Loopでも 他にも方法があるのは知っています。勉強の為に、For~Eachでの やりかたを知りたいのです。また、構造体配列ではなく、多次元配列での 特定の次元要素を同様に処理する方法も知りたいです。 どなたかご教授お願いできれば幸いです。 ネット上でそれなりに調べましたが、目的に沿う情報は みつけることができません。 Public Class Form1 Structure STR Dim Data1 As Double Dim Data2 As Double Dim Data3 As Double End Structure Private Sub Button1_Click(sender As System.Object, _ e As System.EventArgs) Handles Button1.Click Dim Str_1(10000) As StR Dim Rn As New System.Random() For i = 0 To 9999 Str_1(i).Data3 = Rn.Next(100) Next '以降いろんな処理をやる ' ' 'このあと For~Nex ではなくFor Each をつかってメンバーDat3の合計を得るには? Dim sum As Double For Each X As ???_1 in ???_2 '???_1 と ???_2 の記述がわからない sum += X Next Label1.Text = sum.ToString End Sub End Class

  • For Each  すべてループされない?アクセス

    For Each ctl In Forms(FormName).Controls Debug.Print ctl.Name If ctl.ControlType = acTextBox Then If ctl.Name Like "削除*" Then DeleteControl FormName, ctl.Name End If End If Next ctl こういうループの仕方は、完全型ではないのでしょうか? フォーム上に「削除」で始まるテキストボックスをすべて削除したいのですが 例えば4個あれば、2個のコントロールしか削除されません。 コントロールを削除することにより、インデックスが狂うのでしょうか?

  • 指定したセルに1がない時、For を抜けたいのですが・・・

    Office XP Personal 2002 Excel 2002 指定した範囲セルに1がない時、下記の1つの For だけ を抜けたいのですが・・・ どのように変更すればよろしいでしょうか? よろしくお願い致します。 Sub test() Dim i As Integer Dim n As Range For i = 1 To Worksheets.Count - 1  Worksheets(i).Activate  For Each n In .Range("E6", .Range("E6").End(xlDown))   If Not n.Cells.Value = 1 Then   End If   Next n    MsgBox "「1」 がありません。", 48   Exit For  'For Each n In .Range("E6", .Range("E6").End(xlDown))   '続く   '・    '・ End Sub

  • このコード(For Each…)ですが、うまく実行できません!

    EXEL 2002 です。 下記コードなのですが、 うまくできません、 「For Each…」の下2行がエラーとなります。 何卒、ご教示よろしくお願い致します。 -------------------- Sub 下方表の各列を上方へ貼付る() '下方の表の各列を、上方に貼り付ける Dim r As Range With Worksheets(Worksheets.Count - 1) For Each r In .Range("G40:Z40") .Range(r.Offset(0, 0), .Range(r.Offset(0, 0)).End(xlDown)).Copy _ .Range (r.Offset(-38, 1)) Next r End With End Sub

  • VBA For Eachの使い方

    For Each x In Range("A1:G1") このようなコードにおいて、A1からG1の全てに対して処理を行うのではなく、A1とC1とE1とG1に対して処理を行い、B1とD1とF1は飛ばして処理をしないようにするにはどうすれば良いですか?

  • コレクションの取り扱い

    宜しくお願いします。 下記のようなソースでクラスをコレクション化したのですが for each文で値が変わってくれません。(泣) 何か基本的な事だと思うのですが、お知恵を頂ければ幸いです。m(__)m 'emp Collection Public Class clsEmp Inherits System.Collections.ArrayList '色々とメソッドを追加予定・・・ End Class 'empの構造体 Public Structure emp Public ID As Integer Public name As String Public score As Integer Public Sub New(ByVal ID_ As Integer, ByVal name_ As String) Me.ID = ID_ Me.name = name_ Me.score = -1 End Sub End Structure 'モジュール 'empのCollectionを宣言 Private emps As New clsEmp Private Sub Form_Load(・・・) Dim i% 'とりあえず、インスタンスを作る For i = 0 To 10 emps.Add(New emp(i, "test" & i)) Next End Sub Private Sub Button3_Click(・・・) Dim emp_ As emp '初期化してみる For Each emp_ In emps Debug.WriteLine(emp_.name) emp_.score = 0 Next '確認用 For Each emp_ In emps Debug.WriteLine(emp_.score) Next End Sub

専門家に質問してみよう