Instanz aus Sequenz/Array kopieren und gleichzeitig Eigenschaften ändern

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Instanz aus Sequenz/Array kopieren und gleichzeitig Eigenschaften ändern

    Hallo

    Ich suche eine Möglichkeit einfach und unkompliziert Eingenschaften von Objekten beim Kopieren zu ändern.
    Ein konkretes Beispiel:
    In der List AllWaves befinden sich Objekte des Typs Objects.Emitters.SingleWave
    Unter gewissen Umständen muss ein Objekt dieses Arrays kopiert werden. Dabei müssen nur drei von neun Eigenschaften geändert werden.
    Darum wäre es nicht so sinnvoll eine Instanz der Klasse neu zu erstellen, alle Eigenschaften separat zu übernehmen und dort die entsprechenden Eigenschaften zu ändern. Das würde nämlich so aussehen:

    VB.NET-Quellcode

    1. AllWaves.Add(New Objects.Emitters.SingleWave(.PositionX, Berechnungen, .MaximumRadius, .AutoMaximum, .WaveColor, .WaveWidth, .Radius, Berechnungen, Berechnungen))

    Mit Berechnungen sind hierbei die drei Parameter gemeint, die neu bestimmt werden müssen.

    Ich hätte da an so etwas ähnliches wie das With Schlüsselwort gedacht. Allerdings geht das nur beim Erstellen von neuen Instanzen:

    VB.NET-Quellcode

    1. AllWaves.Add(New Objects.Emitters.SingleWave(...) With {.Eigenschaft = Wert})


    Aber nicht beim Verwenden von existierenden Instanzen:

    VB.NET-Quellcode

    1. AllWaves.Add(AllWaves(ThisIndex) With {.Eigenschaft = Wert})



    Gibt es so eine Möglchkeit? Oder muss ich es doch anders schreiben?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Danke, das bringt aber zwei Probleme mit sich:
    Erstens gibt die Clone Funktion Object zurück wenn sie ICloneable implementieren soll. Wenn ich Object zu SingleWave ändere kann sie ICloneable nicht mehr implementieren und dann kann ich es gleich weglassen.
    Zweitens Muss ich dann erst wieder das schreiben:

    VB.NET-Quellcode

    1. Return New SingleWave(PositionX, PositionY, etc.)

    Und wenn ich dann auch noch die Parameter ändern will muss ich das der Funktion extra übergeben, was dazu führt, dass ich zwei Funktionen übergeben muss. Denn einmal wird die X Position verändert und ein anderes Mal die Y Position.

    Leider auch keine ideale Lösung.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Das übliche Vorgehen ist glaub, der Klasse einen sog. Copy-Konstruktor zu gewähren, iwie sowas:

    VB.NET-Quellcode

    1. Sub New(template As WaveDingsbums, gutes As Integer, nützliches As Single und schönes As Double)
    2. '...


    Die ICloneable-Schnittstelle magichnich, weil sie gibt typ Object zurück, anstatt den richtigen Typ.
    Ansatz:
    codeproject.com/KB/tips/SerializedObjectCloner.aspx

    Dann evtl ein eigenes Interface definieren: IMyClonable(of T). Dann per Mixin/Extension "Trick" erweitern und in jede Klasse "einbauen", die es können soll.
    Dürfte nicht sonderlich performant sein, aber vermutlich ziemlich flexibel?

    Könnte man ggf noch erweitern indem die Clone Methode Ein Tuple Array entgegennimmt, das jeweils den "Namen" der eigenschaft und den "neuen" Wert (als object) enthält. Nach dem deserialize dann halt per Reflection setzen.

    Wie gesagt: Einfach mal so ins Blaue gedacht!

    Ach so: Mehr zum Thema ggf hier: csharp411.com/c-object-clone-wars/
    Danke für die Ansätze, aber Performance ist her sehr wichtig. Wenn man das Programm ausprobiert hat (Wave Simulator v1.1 im Showroom) weiß man, wie es in die Knie geht wenn sich viel auf dem Feld tut.

    Also wenn es nicht anders geht:

    VB.NET-Quellcode

    1. AllWaves.Add(New Objects.Emitters.SingleWave(.PositionX, Berechnungen, .MaximumRadius, .AutoMaximum, .WaveColor, .WaveWidth, .Radius, Berechnungen, Berechnungen))

    ist ja nicht unperformant, es schädigt nur ein Bisschen die Übersichtlichkeit des Codes. Die Welt geht deswegen schon nicht unter^^.
    Ich hätte da nur gehofft eine schöne Variante zu finden.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Niko Ortner schrieb:

    Danke für die Ansätze, aber Performance ist her sehr wichtig.

    eher im gegenteil, wenn ich recht verstehe. Dazu müsste ich mehr über das SingleWave-Dingsbums wissen.
    Also wenn das ein großes Objekt ist, welches aufwändig verarbeitet wird, geht die performance bei der Verarbeitung drauf, nicht beim Klonen, und ob man nun so oder anners klont, kann da performancemäßig ühaupt nix reißen.

    Wenn aber die Verarbeitung grade in massenhaften Klon-Vorgängen kleiner Dingsbumse besteht, dann spielt das natürlich eine rolle.
    Ok, ich erkläre:
    Das Wave-Dingsbums stellt einen Kreis auf einem Spielfeld dar. Die Verarbeitung macht eigentlich nur, dass zum Radius des jeweiligen Objektes ein gewisser Wert addiert wird. Allerdings wurde gewünscht, dass ich Reflektionen einbaue. Das heißt ich muss beim Auftreffen einer Welle auf eine Wand die Welle auf die andere Seite der Wand spiegeln und dabei nur die Winkel des angezeigten Kreisbogens ändern bzw. nur entweder die X oder die Y Position der Welle.
    Wenn sich entsprechend viele Wellen auf dem Spielfeld befinden müssen auch entsprechend viele geklont werden, und da ist es wichtig auf Performance zu achten denn ich kann hier jede Millisekunde gebrauchen weil ja nicht nur Radien inkrementiert werden, sondern auch noch einen Haufen Zähler. Zusätzlich gibt es noch Objekte, die für jede vorhandene Welle überprüfen müssen ob sie sich über dem Objekt befindet, das dauert auch seine Zeit. Und das Ganze muss noch gezeichnet werden (Das nimmt die meiste Zeit in Anspruch).
    Solange es nicht viele Objekte sind geht es schon, aber wenn es mehrere sind sollte das Programm nicht gleich in die Knie gehen.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    ach - und ich dachte, das hätte wass mittm Audio.wave-Format zu tun!

    egal - du hast selbst den Performance-Flaschenhals genannt: das Zeichnen
    ja, und da kannst du am Klon-Vorgang optimieren, bis du schwarz wirst, mehr als ein paar promille kriegste da für die gesamt-Performance nicht raus, denn die wird ja ganz woanners verbraten.
    Es mag stimmen, dass die Performance wo anders ganz besonders "verbraten" wird, aber 7 Sekunden + 3 Sekunden = 10 Sekunden. Wenn ich die 3 Sekunden auf 2 Sekunden optimiere ergibt sich 9 Sekunden. Das ist zwar keine Hammer Optimierung, aber immer noch weniger als 10 Sekunden. Auch wenn sich das auf die gesamte Performance nur gering auswirkt: Mehrere solcher kleiner Optimierungen ergeben insgesamt schon eine Merkbare Verbesserung.

    Aber: Gibt es so eine Möglichkeit oder muss ich es anders schreiben?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    vermutlich verkennst du die Relationen. Ich jdfs. würde eher schätzen: 9,99s und 0,01s. Und nun kannst du beim Clonen mw. die 0,01s optimieren.

    fiel fergnügen.


    wg Möglichkeiten: copy-Konstruktor habichschon genannt, der hat ausserdem auch keinerlei performance-lastigen Overhead (was wie gesagt, nicht von Belang ist)