17

NeededListこのリストの各項目をチェックして、データベースに存在するかどうかを確認する必要があるという名前のリストがあります。データベースに存在する場合は、リストから削除する必要があります。しかし、リストを反復している間はリストを変更できません。どうすればこれを機能させることができますか?

これまでの私のコードは次のとおりです。

For Each Needed In NeededList
        Dim Ticker = Needed.Split("-")(0).Trim()
        Dim Year = Needed.Split("-")(1).Trim()
        Dim Period = Needed.Split("-")(2).Trim()
        Dim Table = Needed.Split("-")(3).Trim()
        Dim dr As OleDbDataReader
        Dim cmd2 As New OleDb.OleDbCommand("SELECT * FROM " & Table & " WHERE Ticker = ? AND [Year] = ? AND Period = ?", con)
        cmd2.Parameters.AddWithValue("?", Ticker)
        cmd2.Parameters.AddWithValue("?", Year)
        cmd2.Parameters.AddWithValue("?", Period)
        dr = cmd2.ExecuteReader
        If dr.HasRows Then
            NeededList.Remove(Needed)
        End If
Next
4

7 に答える 7

37

いいえ、for each を使用してそれを行うことはできませんが、昔ながらの for .. ループを使用して行うことができます。
トリックは、最後から開始して逆方向にループすることです。

For x = NeededList.Count - 1 to 0 Step -1
    ' Get the element to evaluate....
    Dim Needed = NeededList(x)
    .....
    If dr.HasRows Then
        NeededList.RemoveAt(x)
    End If
Next

現在の要素が削除されたために要素をスキップするリスクがないため、この方法でループにアプローチする必要があります。

たとえば、コレクションの 4 番目の要素を削除すると、その後、5 番目の要素が 4 番目になります。But then the indexer go up to 5. このようにして、前の 5 番目の要素 (現在は 4 番目の位置) は評価されません。もちろん、インデクサーの値を変更しようとすることもできますが、これは常に悪いコードと発生するのを待っているバグで終わります。

于 2013-10-08T15:47:30.787 に答える
17

安全のために、次のコマンドでコピーを作成しToList()ます。

For Each Needed In NeededList.ToList()
    Dim Ticker = Needed.Split("-")(0).Trim()
    ...
    If dr.HasRows Then
        NeededList.Remove(Needed)
    End If
Next
于 2013-10-09T09:40:12.897 に答える
4

ステップ -1 ですべてのインデックスを反復処理する For ループを使用できます。

For i as Integer = NeededList.Count - 1 to 0 Step -1

    Dim Needed = NeededList(i)

    'this is a copy of your code
    Dim Ticker = Needed.Split("-")(0).Trim()
    Dim Year = Needed.Split("-")(1).Trim()
    Dim Period = Needed.Split("-")(2).Trim()
    Dim Table = Needed.Split("-")(3).Trim()

    Dim dr As OleDbDataReader
    Dim cmd2 As New OleDb.OleDbCommand("SELECT * FROM " & Table & " WHERE Ticker = ? AND [Year] = ? AND Period = ?", con)
    cmd2.Parameters.AddWithValue("?", Ticker)
    cmd2.Parameters.AddWithValue("?", Year)
    cmd2.Parameters.AddWithValue("?", Period)
    dr = cmd2.ExecuteReader

    'MODIFIED CODE
    If dr.HasRows Then NeededList.RemoveAt(i)

Next i
于 2013-10-08T15:46:27.813 に答える
0

リストの要素の順序を逆にして、 と 拡張機能を使用することもFor EachできIEnumerable CastますReverse

List(Of String) を使用した簡単な例:

For Each Needed In NeededList.Cast(Of List(Of String)).Reverse()
    If dr.HasRows Then
        NeededList.Remove(Needed)
    End If
Next
于 2016-05-26T02:55:53.993 に答える
0

これはどうですか(反復は必要ありません):

NeededList = (NeededList.Where(Function(Needed) IsNeeded(Needed)).ToList

Function IsNeeded(Needed As ...) As Boolean
    ...
    Return Not dr.HasRows
End Function
于 2016-09-20T00:08:12.143 に答える
0

いいえ、作業中のリストから削除することはできません。たとえば、For Each Str As String In listOfStrings If Str.Equals("Pat") Then Dim index = listOfStrings.IndexOf(Str) listOfStrings .RemoveAt(index) End If Next

しかし、この方法はあなたのリストのコピーを作成し、それから削除することができます。次

于 2015-04-17T11:51:37.033 に答える