Schreibweise verkürzen?

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Bluespide.

    Mit LINQ normalerweise:

    VB.NET-Quellcode

    1. For Each C In A.Select(Function(x) x.VerbindungL).Select(Function(x) x.VerbindungL)
    2. Next
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    vico255 schrieb:

    Gibt es für solch verschachtelten Schleifen auch kürzere Schreibweisen?
    Zumindest nichts, was einfacher lesbar wäre, ausser, dass du die ​As XX bei Option Infer On weglassen könntest.
    Interessant wäre es dann, wenn die Verschachtelungstiefe variabel ist.
    Dann kannst du mit rekursiven Aufrufen arbeiten.

    Sind die Datentypen AA, BB, CC unterschiedlich?
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Morrison schrieb:

    performanter?

    Jenach basistyp der verwendet wird sogar im Gegenteil:
    List z.b. hat eine struct als enumerator(was auch durchaus Sinn ergibt). Enumerators und Enumerables sind in .Net eine sehr interessante Sache, da einer for-Schleife egal ist ob das objekt IEnumerable ist oder nicht, alles was wichtig ist, ist dass es eine Funktion GetEnumerator ohne parameter und mit Rückgabetyp gibt. Dieser Rückgabetyp muss auch kein IEnumerator sein, es ist nur wichtig, dass das objekt ein bool MoveNext hat und eine T Current-Property.
    C# geht dann einfach hin und ruft das GetEnumerator der obersten ebene auf.
    Bei einer List(Of T) sieht das ca. so auf

    VB.NET-Quellcode

    1. Public Function GetEnumerator() As Enumerator ' Structure weiter unten
    2. Return New Enumerator(Me)
    3. End Function
    4. Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
    5. Return GetEnumerator()
    6. End Function
    7. Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
    8. Return GetEnumerator()
    9. End Function
    10. Public Structure Enumerator
    11. Public Property Current() As T
    12. Public Function MoveNext() As Boolean
    13. ....
    14. End Function
    15. End Structure

    aufgerufen in der foreach wird die erste GetEnumerator es wird eine struct auf dem stack erzeugt und die wird verwendet, ohne dass sich .Net für IEnumerable oder IEnumerator interessiert.
    LinQ Funktionen erwarten jedoch ein IEnumerable und haben keine Speziallisierungen für List(Of) oder was auch immer. Dies bedeutet, dass nur die zweite GetEnumerator Funktion verwendet werden kann, da das Interface IEnumerable(Of T) ja nichts von der ersten weiß. Da Funktion nummer 2 ein IEnumerator(Of T) ist und nicht die Enumerator struct haben wir ein Problem. Denn structs sind erst ein mal auf dem Stack. Interfaces auf dem Stack hingegen gibt es nicht, das muss man jetzt irgendwie aber hinbekommen. Was kann also .Net tun? Es macht eine sogenannte Boxing-Allokation. Was genau das macht ist es legt auf dem Heap ein neues objekt an mit der größe der struct und kopiert diesen struct inhalt dort hinein. Nun haben wir das ganze auf dem Heap und können auch das Interface wunderbar verwenden und einfach die Referenz dieses geboxten(Ist ja quasi eine Box, die die struct enthält) objekts zurückgeben. Irgendwann später muss das ganze objekt natürlich auch wieder vom Heap gelöscht werden, was bei der foreach-Version nicht nötig war, da diese direkt die struct verwendet und somit alles auf dem stack bleibt...

    Nun ist eine boxing allokation nicht übertrieben teurer und ist performance technisch erstmal gut ignorierbar. Problematisch wird in den meisten fällen eher das aufräumen dieser Enumeratoren vom Heap, da es sich jenach dem um sehr viele kleine und kurzlebige objekte handeln kann. Für Businessanwendungen meist irrelevant, aber wenn es um vorhersehbare Rechenzeiten geht, dann ist soetwas tötlich. Zum Beispiel bei Spielen sollte man sowas immer vermeiden. Deshalb verwende ich bei Spielen nie LinQ.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Nein es ist schneller, es sei denn du verwendest LinQ, dann hat es einen kleinen overhead und eine Klasse wäre für diesen Fall dann tatsächlich sinnvoller. Aber wenn es eine Klasse wäre, dann wäre es schlimmer, da man dann den GC und heap alloc overhead nicht verhindern könnte. Den overhead den eine struct ggü. einer class bei Verwendung direkt über die Interfaces hat ist nur das kopieren des Speichers, was bei dem iterator 8-12 bytes sind. Das ist wirklich marginal. Aber umgekehrt wäre der overhead unterschied eben viel größer...

    Also wär es so performant wie möglich haben will und ohne spätere Nachwirkungen durch den GC, der verwendet foreach, wem das egal ist, der kann ruhig LinQ verwenden, denn in den meisten Fällen ist es nur ein kleiner overhead und dieser gilt hauptsächlich zu Beginn beim erzeugen des Enumerators und am Ende beim löschen, beim iterieren sollte ziemlich dasselbe rauskommen...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---