myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Grundlagen von C# » Values von Properties beim Clonen auf null prüfen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Values von Properties beim Clonen auf null prüfen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Glowhollow Glowhollow ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.07.2018
Beiträge: 74


Glowhollow ist offline

Values von Properties beim Clonen auf null prüfen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja, der nervige hier ;) bin wieder da :D

Ich habe eine Copy Funktion.

C#-Code:
public void CopyValues<T>(T target, T source)
        {
            Type t = typeof(T);

            var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

            foreach (var prop in properties)
            {
                var value = prop.GetValue(source, null);
                if (value != null)
                    prop.SetValue(target, value, null);
            }
        }

Die Properties werden gut kopiert, kein thema. Jetzt habe ich aber Properties die 2 Subproperties beinhalten können.

In unserem Beispiel nennen wir sie jetzt content.link und content.value.

Jetzt ist es ja hier nicht zu unterscheiden ob content.link und content.value ungleich null sind.

Gibts dafür nen lösungsansatz ?
10.10.2018 16:38 Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.450
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi Glowhollow,

wieder einmal hast du das Rad neu erfunden und eine Methode geschrieben, die es bereits im Framework gibt:  Object.MemberwiseClone.

Wenn ich deine Frage jetzt richtig verstehe (was wirklich nicht leicht ist), dann willst du vermutlich eine  "Deep Copy"-Variante deiner Implementierung. Dazu mußt du Rekursion verwenden.

Vor allem aber hilft es bei der Umsetzung, sich vorher zu informieren, was es gibt, und wie es andere Entwickler umsetzen. Du kannst davon ausgehen, daß du nicht der erste Entwickler auf der Welt bist, der Objekte kopieren oder etwas ungewöhnliche JSON-Dateien parsen will. Ein paar Minuten im Internet recherchieren, kann dir viel Zeit sparen, Sachen zu implementieren, die es bereits gibt. Oder auch: "Weeks of coding can save you hours of planning."

Siehe auch:  [Tipp] Schau in die Doku! - Möglichkeiten der Informationsgewinnung
10.10.2018 16:50 Beiträge des Benutzers | zu Buddylist hinzufügen
markl markl ist männlich
myCSharp.de-Mitglied

avatar-4095.gif


Dabei seit: 29.09.2016
Beiträge: 77
Entwicklungsumgebung: VS2017 and VSC


markl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Die MSDN beschreibt dies in den Remarks von MemberwiseClone:

Dein MemberwiseClone führt ein "shallow copy" durch.

Möchtest du ein DeepCopy, dann gibt es da viele Wege (z.B. durch Serialisierung).
Siehe dazu:

 https://docs.microsoft.com/en-us/dotnet/api/system.object.memberwiseclone?redirectedfrom=MSDN&view=netframework-4.7.2#remarks
10.10.2018 16:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.450
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top



Zitat von markl:
z.B. durch Serialisierung

Serialisierung will er ja gerade  selbst implementieren
10.10.2018 17:02 Beiträge des Benutzers | zu Buddylist hinzufügen
markl markl ist männlich
myCSharp.de-Mitglied

avatar-4095.gif


Dabei seit: 29.09.2016
Beiträge: 77
Entwicklungsumgebung: VS2017 and VSC


markl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von MrSparkle:


Zitat von markl:
z.B. durch Serialisierung

Serialisierung will er ja gerade  selbst implementieren

@MrSparkle: Oh ja hast ja recht :-). Das man "Serialisierung" nicht selber implementiert, wurde ja schon diskutiert. Der Rest des MSDN-Artikels wird Glowhollow sicherlich weiter bringen.
10.10.2018 17:14 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.594
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist online Füge T-Virus Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wen du nicht, wie von MrSparkle vermutet gegen Serialisierung abgeneigt bist, kannst du dies mit dem Serializable Attribute und einer einfachen Copy Methode umsetze.

Bsp:

C#-Code:
public static T DeepClone<T>(T obj)
{
    using (var ms = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(ms, obj);
        ms.Position = 0;

        return (T) formatter.Deserialize(ms);
    }
}

Da musst du dich überhaupt nicht um die ganzen Probleme mit einer händischen Lösung rumschlagen ud dürftest alleine damit schon zich Stunden an Zeit/Arbeit einsparen.

Falls du aber auch hier wieder, entgegen jeder Empfehlung, an einer eigenen Lösung festhalten willst, wirst du wohl oder über nicht um eine rekursive Lösung kommen.
Hier musst du eben über alle Ebene von Objekten laufe.
Also Listen/Arrays etc. was eben ein Container für Objekte sein kann und musst diese dann kopieren.

Aber ganz ehrlich, die Arbeit kannst du dir mit einfachen .NET Bordmitteln sparen.
Es gibt einfach keinen rationalen Grund auch hier wieder auf einfache Bordmittel, die genau dein Vorhabe abdecken, zu verzichten.

T-Virus

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von T-Virus am 10.10.2018 17:19.

10.10.2018 17:18 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Glowhollow Glowhollow ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.07.2018
Beiträge: 74

Themenstarter Thema begonnen von Glowhollow

Glowhollow ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Machmal denke ich echt, ich spreche eine andere Sprache :).

Nun, ich bin ja fast fertig mit dem Deserializer.

Aber, ich habe noch folgendes Problem. Achtung Wall of Text.

Die CopyFunktion, kopiert alles so wie ich es brauche, nicht rekursiv, das ist hier auch nicht notwendig. Das einzige was ich jetzt noch zum Abschluss brauche ist es zu prüfen, ob beim Deserialisieren (was in kleinen schritten passiert), Werte vorhanden sind.

So soll im Target, werte stehen, die von der Source kopiert werden. Richtig. Die Source sind aber nur elemente, werden aber jedoch komplett in der ganzen bandbreite deserialisiert. Das heißt, das ich im Target nur die Werte haben möchte, die auch deserialisiert sind. Da Source, aber abgesehen von einem einzelnen Restschritt, jeweils nur 1 Wert drin steht. Ist es so, das die anderen Werte auf null sind.

Diese sollen nicht kopiert werden. Das macht die Copy Funktion aber auch.

Jetzt ist es aber so, das der Bereich, in dem es zu einem Datensatz, mehrere werte gibt. In diesem fall, z.bsp. content.link und content.value, ist ja content gesetzt. jedoch sind die werte link und value auf null.

Jetzt erkennt die Copy Funktion das, sieht, content ist nicht null, und kopiert fröhlich drauf los und überschreibt mir die hart erarbeiteten Ergebnisse.

Das möchte ich verhindern. Am liebsten wäre mir eine if abfrage mit der ich prüfen kann, ob .... . link und .... value (es gibt da n ganzen satz von) jeweils null sind.

Ich würde ja gerne sowas in c#-konformer Syntax realisieren.

if (value != null && value.category.subcategory == null)

Aber irgendwie finde ich nicht die passenden Worte für.
10.10.2018 17:49 Beiträge des Benutzers | zu Buddylist hinzufügen
Glowhollow Glowhollow ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.07.2018
Beiträge: 74

Themenstarter Thema begonnen von Glowhollow

Glowhollow ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

C#-Code:
public void CopyValues<T>(ref T target, T source)
        {
            Type t = source.GetType();

            var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

            foreach (var prop in properties)
            {
                if (prop.PropertyType.IsValueType || prop.PropertyType == typeof(string))
                {
                    var value = prop.GetValue(source, null);
                    if (value != null)
                    {
                        prop.SetValue(target, value, null);
                    }
                }
                else
                {
                    var sourceValue = prop.GetValue(source, null);
                    var targetValue = prop.GetValue(target, null);

                    if (targetValue == null)
                    {
                        targetValue = Activator.CreateInstance(sourceValue.GetType());
                    }

                    CopyValues(ref targetValue, sourceValue);

                    prop.SetValue(target, targetValue);
                }
            }
        }

das wars. Viel Spass mit dem Code.
10.10.2018 18:22 Beiträge des Benutzers | zu Buddylist hinzufügen
markl markl ist männlich
myCSharp.de-Mitglied

avatar-4095.gif


Dabei seit: 29.09.2016
Beiträge: 77
Entwicklungsumgebung: VS2017 and VSC


markl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Aber das ist doch -Ansatzweise- sowas wie DeepCopy geworden.
Somit auch das was MrSparkle dir vorgeschlagen hat.

Nachtrag:
Ich hab das jetzt nicht im Compiler geprüft, aber führt

C#-Code:
CopyValues(ref targetValue, sourceValue);

nicht zu

C#-Code:
CopyValues<object>(ref targetValue, sourceValue);

somit zu einem falschen ...

C#-Code:
Type t = source.GetType();

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von markl am 10.10.2018 18:44.

10.10.2018 18:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als ein Jahr.
Der letzte Beitrag ist älter als ein Jahr.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 21.09.2020 12:02