Fehler in For...Next-Schleife

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Naifu.

    Fehler in For...Next-Schleife

    So, ich bins mal wieder,

    bin grad beim Schreiben eines Getters auf ein Problem gestoßen, das ich so noch nicht kenne und bin etwas überfragt:

    VB.NET-Quellcode

    1. Public ReadOnly Property AnzuzeigendeMusiktitel As ObservableCollection(Of MP3FileInfo)
    2. Get
    3. Dim retList = New List(Of MP3FileInfo)
    4. For Each item In InhaltGesamt
    5. If item.Stream = False Then
    6. retList.Add(item)
    7. End If
    8. Next
    9. Dim filteredList1 As List(Of MP3FileInfo) = retList
    10. Dim filteredList2 As List(Of MP3FileInfo) = retList
    11. Dim filteredList3 As List(Of MP3FileInfo) = retList
    12. If Not String.IsNullOrEmpty(TextFilter) Then
    13. filteredList1 = retList.Where(Function(x) x.Musiktitel.ToLower.Contains(TextFilter)).ToList()
    14. filteredList2 = retList.Where(Function(x) x.Album.ToLower.Contains(TextFilter)).ToList()
    15. filteredList3 = retList.Where(Function(x) x.Interpret.ToLower.Contains(TextFilter)).ToList()
    16. End If
    17. For Each item In filteredList2
    18. filteredList1.Add(item)
    19. Next
    20. For Each item In filteredList3
    21. filteredList1.Add(item)
    22. Next
    23. Return New ObservableCollection(Of MP3FileInfo)(filteredList1.OrderBy(Function(o) o.Musiktitel).GroupBy(Function(f) f.Musiktitel).Select(Function(g) g.First()).ToList())
    24. End Get


    Da kommt der Fehler in Zeile 19:
    Die Sammlung wurde geändert. Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden.

    Man kann in den Ausnahmeeinstellungen den Fehler übergehen. Sollte ich das einfach tun oder ist das suboptimal?
    BIst du dir sicher, dass es daran liegt? Das hier funktioniert nämlich:

    VB.NET-Quellcode

    1. Public ReadOnly Property AnzuzeigendeAlben As ObservableCollection(Of MP3FileInfo)
    2. Get
    3. Dim retList = New List(Of MP3FileInfo)
    4. For Each item In InhaltGesamt
    5. If item.Stream = False Then
    6. retList.Add(item)
    7. End If
    8. Next
    9. Dim filteredList1 As List(Of MP3FileInfo) = retList
    10. Dim filteredList2 As List(Of MP3FileInfo) = retList
    11. If Not String.IsNullOrEmpty(TextFilter) Then
    12. filteredList1 = retList.Where(Function(x) x.Album.ToLower.Contains(TextFilter)).ToList()
    13. filteredList2 = retList.Where(Function(x) x.Interpret.ToLower.Contains(TextFilter)).ToList()
    14. For Each item In filteredList2
    15. filteredList1.Add(item)
    16. Next
    17. End If
    18. Return New ObservableCollection(Of MP3FileInfo)(filteredList1.OrderBy(Function(o) o.Album).GroupBy(Function(f) f.Album).Select(Function(g) g.First()).ToList())
    19. End Get
    20. End Property
    @kafffee Probier mal, Clone zu erstellen:

    VB.NET-Quellcode

    1. Dim filteredList1 As List(Of MP3FileInfo) = New List(Of MP3FileInfo)(retList)
    2. Dim filteredList2 As List(Of MP3FileInfo) = New List(Of MP3FileInfo)(retList)
    3. Dim filteredList3 As List(Of MP3FileInfo) = New List(Of MP3FileInfo)(retList)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Naifu schrieb:

    Sag ich doch.

    Sagst du zwar, stimmt nur nicht ganz. Das .ToList() sorgt für eine Kopie. Selbst ohne Bedingung.

    Beispiel:

    C#-Quellcode

    1. List<int> a = new List<int>();
    2. List<int> b = a.ToList();
    3. Console.WriteLine(a == b);

    Ergebnis: False

    Ich schätze aber weil die Kopie hinter dem If steht, gibt die Möglichkeit das es eben die selbe Liste ist, also wenn er nicht in das ​If rein läuft. Dann sollte es zu einer Exception kommen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bluespide“ ()

    kafffee schrieb:


    VB.NET-Quellcode

    1. Public ReadOnly Property AnzuzeigendeAlben As ObservableCollection(Of MP3FileInfo)
    2. Get
    3. Dim retList = New List(Of MP3FileInfo)
    4. For Each item In InhaltGesamt
    5. If item.Stream = False Then
    6. retList.Add(item)
    7. End If
    8. Next
    9. Dim filteredList1 As List(Of MP3FileInfo) = retList
    10. Dim filteredList2 As List(Of MP3FileInfo) = retList
    11. If Not String.IsNullOrEmpty(TextFilter) Then
    12. filteredList1 = retList.Where(Function(x) x.Album.ToLower.Contains(TextFilter)).ToList()
    13. filteredList2 = retList.Where(Function(x) x.Interpret.ToLower.Contains(TextFilter)).ToList()
    14. For Each item In filteredList2
    15. filteredList1.Add(item)
    16. Next
    17. End If
    18. Return New ObservableCollection(Of MP3FileInfo)(filteredList1.OrderBy(Function(o) o.Album).GroupBy(Function(f) f.Album).Select(Function(g) g.First()).ToList())
    19. End Get
    20. End Property
    Dir ist schon klar, dass die Methode ziemlich KrautnRüben ist, odr?
    der erste Schritt wäre, mal zu kommentieren, was sie eiglich tun soll.
    @ErfinderDesRades

    VB.NET-Quellcode

    1. Public ReadOnly Property AnzuzeigendeAlben As ObservableCollection(Of MP3FileInfo) 'gebunden an Listbox
    2. Get
    3. Dim retList = New List(Of MP3FileInfo)
    4. For Each item In InhaltGesamt 'InhaltGesamt: Liste mit Musiktitelinfos
    5. If item.Stream = False Then 'Prüfen ob Stream oder Datei
    6. retList.Add(item) 'wenn ja: zufügen zu retlist zur weiteren Filterung
    7. End If
    8. Next
    9. Dim filteredList1 As List(Of MP3FileInfo) = retList
    10. Dim filteredList2 As List(Of MP3FileInfo) = retList
    11. If Not String.IsNullOrEmpty(TextFilter) Then
    12. filteredList1 = retList.Where(Function(x) x.Album.ToLower.Contains(TextFilter)).ToList() 'Textfilter: Eigenschaft an Textbox.Text gebunden zur Suche nach String in Alben und Interpreten
    13. filteredList2 = retList.Where(Function(x) x.Interpret.ToLower.Contains(TextFilter)).ToList()
    14. For Each item In filteredList2 'zusammenfügen der Listen
    15. filteredList1.Add(item)
    16. Next
    17. End If
    18. Return New ObservableCollection(Of MP3FileInfo)(filteredList1.OrderBy(Function(o) o.Album).GroupBy(Function(f) f.Album).Select(Function(g) g.First()).ToList()) 'alphabetisch sortieren und doppelte Einträge entfernen
    19. End Get
    20. End Property


    Besser so? Der Code dient dazu, Musik nach bestimmten Kriterien zu filtern, zu durchsuchen und anzuzeigen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Kriterien: obs ein MP3 File oder Stream ist

    jo, dassis auch so eine Sache:

    VB.NET-Quellcode

    1. 'Prüfen ob Stream oder Datei
    2. 'wenn ja: zufügen zu retlist zur weiteren Filterung
    Also "Prüfen, ob Stream oder Datei, und wenn ja..." (hä - watnu?)

    Also die Kriterien in EDR-Sprech:
    Anzuzeigen ist, was Datei ist, und wo Interpret oder Album oder Musiktitel oder Genre den TextFilter enthält.

    So, nun kann man mit KrautnRübn anfangen - zunächstmal darf das nicht in der gebundenen Property selbst ermittelt werden.
    Weil das Gui ruft die Prop ab, wann es will, und kann auch sein sehr oft. Da will man nicht, dass da jedesmal diese aufwändige Logik durchgenudelt wird.

    Sondern die AnzuzeigendeAlben müssen ermittelt werden, wenn TextFilter sich ändert.
    Dort wird die neue OC(Of Mp3Dings) gebildet, und der Property zugewiesen.
    Die Property feuert dann das PropertyChanged, und das Gui updatet sich daraufhin.
    So geht das in Wpf.