none
ArrayList in eine Collection(Of cMyClass) RRS feed

  • Frage

  • Hallo Leute,
    ich möchte einfach eine ArrayList (beinhaltet Objekte vom Typ cMyClass) in eine Collection(Of cMyClass) konvertieren ohne
    dabei mit einer Schleife die Elemente einzeln zu übertragen? Geht das auch typneutral?

    Vielen Dank im Voraus


    Christian Tauschek


    Donnerstag, 26. Januar 2017 21:20

Antworten

  • Hallo zusammen,

    die Antworten in Stefans Link beziehen sich vor allem auf List(Of T). Deswegen möchte ich ein bisschen was allgemeines dazu schreiben.

    Erstmal solltest du nach Möglichkeit gar keine ArrayList verwenden sondern immer ein statisch typisiertes Konstrukt wie ein normales Array oder von Anfang an eine List(Of T) oder eine Collection(Of T).

    Wenn du nun eines ins andere umwandeln willst, so kannst du zumeist einen Konstruktor nutzen. Collection(Of T) besitzt lediglich einen der eine IList(Of T) entgegen nimmt. Andere akzeptieren aber auch das grundlegendste IEnumerable(Of T). (Beispielsweise List(Of T))
    Wobei das Umwandeln selbst immer ein durchlaufen der Liste nach sich zieht, da immer eine neue Instanz (selbst wenn der Typ gleich bleibt) erstellt wird. Das Durchlaufen selbst geschieht dabei meistens durch eine foreach-Schleife (bzw. deren Logik). Theoretisch könnte auch einfach das interne Array kopiert werden, aber dafür müsste die Klassen gegenseitig ihr "Inneres" kennen, was unüblich ist.
    Mir wäre jetzt kein Fall bekannt wo ich das Umwandeln mal gebraucht habe, außer vielleicht bei LinQ, aber das basiert ja nicht ohne Grund nur auf IEnumerable(Of T). Von daher mein Tipp: Nutze nach Möglichkeit von Anfang an einen anderen Typ, sodass die leistungsaufwändige Umwandlung unnötig ist.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Donnerstag, 26. Januar 2017 23:08
    Moderator
  • Hallo Christian,

    warum verwendest Du dann überhaupt eine ArrayList?

    Für die Konvertierung an sich schau mal hier:

      http://stackoverflow.com/questions/786268/in-net-how-do-you-convert-an-arraylist-to-a-strongly-typed-generic-list-withou

    Irgendwo wird irgendeine Codestelle trotzdem durch die Elementliste laufen. Anders wird das IMHO nicht zu machen sein.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 26. Januar 2017 22:23
    Moderator
  • Hi Christian,
    ergänzend zu den anderen Beiträgen ist zu vermerken, dass es vorkommen kann, dass von vorhandenen älteren Komponenten nur ArrayList's geliefert werden. Da muss dann konvertiert werden. Nutzen kann man dazu LinQ to Objects für die ArrayList und den Konstruktor, der eine IEnumerable(Of T) akzeptiert. Da eine ArrayList aber Objektverweise auf beliebige Objekte verwalten kann, muss geprüft werden, dass auch der richtige Typ in die typisierte Liste übernommen wird. Im nachfolgenden Beispiel ist das dargestellt. Alle unpassenden Typen werden da aber nicht übernommen. Wenn es anders sein soll, dann müsstest Du etwas detaillierter beschreiben, welche Konvertierungen erforderlich werden können. Denkbar ist auch anstelle einer Liste eine IEnumerable, die, wenn innerhalb einer Methode genutzt, auch mit anonymen Objekten gefüllt sein kann, die aus den Elementen der Arraylist gewonnen werden, z.B. mit ToString.

    Module Module23
      Public Sub Main()
        ' Daten vorbereiten
        Dim al As New ArrayList
        al.Add(New Demo23Data With {.ID = 1, .Info = "Info 1"})
        al.Add(55)
        al.Add("Info 3")
        al.Add(New Demo23Data With {.ID = 4, .Info = "Info 4"})
        ' Aufruf der typisierten Methode
        Dim l2 = (New Demo23).Execute1(Of Demo23Data)(al)
        ' Ergebnis anteigen
        For Each item In l2
          Console.WriteLine($"{item.ID} - {item.Info}")
        Next
        Console.ReadKey()
      End Sub
    
    End Module
    
    Friend Class Demo23
      Public Function Execute1(Of T)(l1 As ArrayList) As List(Of T)
        Return New List(Of T)(From itm In l1 Where itm.GetType = GetType(T) Select CType(itm, T))
      End Function
    End Class
    
    Friend Class Demo23Data
      Friend Property ID As Integer
      Friend Property Info As String
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Freitag, 27. Januar 2017 05:15

Alle Antworten

  • Hallo Christian,

    warum verwendest Du dann überhaupt eine ArrayList?

    Für die Konvertierung an sich schau mal hier:

      http://stackoverflow.com/questions/786268/in-net-how-do-you-convert-an-arraylist-to-a-strongly-typed-generic-list-withou

    Irgendwo wird irgendeine Codestelle trotzdem durch die Elementliste laufen. Anders wird das IMHO nicht zu machen sein.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 26. Januar 2017 22:23
    Moderator
  • Hallo zusammen,

    die Antworten in Stefans Link beziehen sich vor allem auf List(Of T). Deswegen möchte ich ein bisschen was allgemeines dazu schreiben.

    Erstmal solltest du nach Möglichkeit gar keine ArrayList verwenden sondern immer ein statisch typisiertes Konstrukt wie ein normales Array oder von Anfang an eine List(Of T) oder eine Collection(Of T).

    Wenn du nun eines ins andere umwandeln willst, so kannst du zumeist einen Konstruktor nutzen. Collection(Of T) besitzt lediglich einen der eine IList(Of T) entgegen nimmt. Andere akzeptieren aber auch das grundlegendste IEnumerable(Of T). (Beispielsweise List(Of T))
    Wobei das Umwandeln selbst immer ein durchlaufen der Liste nach sich zieht, da immer eine neue Instanz (selbst wenn der Typ gleich bleibt) erstellt wird. Das Durchlaufen selbst geschieht dabei meistens durch eine foreach-Schleife (bzw. deren Logik). Theoretisch könnte auch einfach das interne Array kopiert werden, aber dafür müsste die Klassen gegenseitig ihr "Inneres" kennen, was unüblich ist.
    Mir wäre jetzt kein Fall bekannt wo ich das Umwandeln mal gebraucht habe, außer vielleicht bei LinQ, aber das basiert ja nicht ohne Grund nur auf IEnumerable(Of T). Von daher mein Tipp: Nutze nach Möglichkeit von Anfang an einen anderen Typ, sodass die leistungsaufwändige Umwandlung unnötig ist.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Donnerstag, 26. Januar 2017 23:08
    Moderator
  • Hi Christian,
    ergänzend zu den anderen Beiträgen ist zu vermerken, dass es vorkommen kann, dass von vorhandenen älteren Komponenten nur ArrayList's geliefert werden. Da muss dann konvertiert werden. Nutzen kann man dazu LinQ to Objects für die ArrayList und den Konstruktor, der eine IEnumerable(Of T) akzeptiert. Da eine ArrayList aber Objektverweise auf beliebige Objekte verwalten kann, muss geprüft werden, dass auch der richtige Typ in die typisierte Liste übernommen wird. Im nachfolgenden Beispiel ist das dargestellt. Alle unpassenden Typen werden da aber nicht übernommen. Wenn es anders sein soll, dann müsstest Du etwas detaillierter beschreiben, welche Konvertierungen erforderlich werden können. Denkbar ist auch anstelle einer Liste eine IEnumerable, die, wenn innerhalb einer Methode genutzt, auch mit anonymen Objekten gefüllt sein kann, die aus den Elementen der Arraylist gewonnen werden, z.B. mit ToString.

    Module Module23
      Public Sub Main()
        ' Daten vorbereiten
        Dim al As New ArrayList
        al.Add(New Demo23Data With {.ID = 1, .Info = "Info 1"})
        al.Add(55)
        al.Add("Info 3")
        al.Add(New Demo23Data With {.ID = 4, .Info = "Info 4"})
        ' Aufruf der typisierten Methode
        Dim l2 = (New Demo23).Execute1(Of Demo23Data)(al)
        ' Ergebnis anteigen
        For Each item In l2
          Console.WriteLine($"{item.ID} - {item.Info}")
        Next
        Console.ReadKey()
      End Sub
    
    End Module
    
    Friend Class Demo23
      Public Function Execute1(Of T)(l1 As ArrayList) As List(Of T)
        Return New List(Of T)(From itm In l1 Where itm.GetType = GetType(T) Select CType(itm, T))
      End Function
    End Class
    
    Friend Class Demo23Data
      Friend Property ID As Integer
      Friend Property Info As String
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Freitag, 27. Januar 2017 05:15
  • Hallo Peter, Tom, Stefan,
    ich erweitere ein älteres Programm, weshalb ich noch mit ArrayList's zu tun habe.

    Ich habe mir eine Extension für ArrayList's gemacht und deinen Code verwendet. Soweit funktioniert alles.

    Im obigen Code musste ich jedoch das "=" mit einem "Is" ersetzen.
    "itm.GetType = GetType(T)" auf "itm.GetType Is GetType(T)"

    mfg Christian

    Christian Tauschek

    Freitag, 27. Januar 2017 08:25
  • Hi Christian,
    das hast natürlich Recht. Eine Prüfung, ob auf das gleiche Typ-Objekt verwiesen wird, ist besser.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Freitag, 27. Januar 2017 08:41