Benutzer mit den meisten Antworten
Objekte vergleichen

Frage
-
Hallo Gemeinde,
ich habe mehrere Instanzen ein und derselben Klasse.
die teilweise dadurch entstanden das man sie clonete.
Nun sind sie aber bearbeitet worden, teilweise nur geringfügig. Ich möchte nun wissen, wie kann ich , im ersten Schritt, herausbekommen ob Werte geändert wurden?
Im Step 2 möchte ich die Änderungen ermitteln, natürlich sollte dies möglichst schnell geschehen.
Gibt es hierzu bessere Methoden als durch die Propertys zu iterieren?
Danke
Antworten
-
Hallo,
Auf deine Frage gibt es keine eindeutige Antwort, da wir gar nichts von der Klasse wissen, die du instanziiert hast und die Du nun mit einer geklonten Instanz vergleichen möchtest. Wir wissen auch nicht, ob die geänderten Werte, die Du feststellen möchtest, nur Werte sind, die über öffentliche Member erreichbar sind, oder auch interne Werte (Zustand).
Darüber hinaus gibt es unterschiedliche Levels von Klonen: die flache Member-Kopie, bei der nur die Property-Werte auf eine neue Instanz übertragen werden (wie wir sie meist in IClonable-Implementationen finden) und es gibt noch die tiefe Kopie, die oft über binäre Serialisierung in ein MemoryStream erreicht wird.
Und es gibt die unterschiedlichsten Vergleichs-Arten. Und unterschiedliche Überschreibung von Object.Equals: Typen wie String oder Integer überschreiben die geerbte Methode und stellen fest, ob die Werte identisch sind, während die Basisimplementation ein simpler Verweisvergleich ist, der angibt, ob die Referenzen auf das gleiche Objekt verweisen.
Person x = new Person();
Person y = new Person();
Console.WriteLine(x.Equals(y)); // immer falsch (falls Equals nicht überschrieben wurde), da versch. Objekte
Egal ob Du im obigen Beispiel die gleichen Property-Werte einsetzt, die Objekte bleiben verschieden.Wenn es sich um eine eigene Klasse handelt, die Du beliebig verändern kannst, könntest Du einen schnellen binären Vergleich der Instanzen vornehmen, z.B.:
[Serializable] class Person : ICloneable, IComparable<Person>, IEquatable<Person> { public string FirstName { get; set; } public string LastName { get; set; } public object Clone() { return new Person { FirstName = FirstName, LastName = LastName }; } public int CompareTo(Person y) { BinaryFormatter formatter = new BinaryFormatter(); using (MemoryStream memoryStreamX = new MemoryStream()) { using (MemoryStream memoryStreamY = new MemoryStream()) { formatter.Serialize(memoryStreamX, this); formatter.Serialize(memoryStreamY, y); var binaryArrayX = memoryStreamX.GetBuffer(); var binaryArrayY = memoryStreamY.GetBuffer(); if (binaryArrayX.Length != binaryArrayY.Length) return binaryArrayX.Length.CompareTo(binaryArrayY.Length); for (int i = 0; i < binaryArrayX.Length; i++) if (binaryArrayX[i] != binaryArrayY[i]) return binaryArrayX[i].CompareTo(binaryArrayY[i]); } } return 0; } public bool Equals(Person other) { return (this.CompareTo(other) == 0); } public override bool Equals(object obj) { return (this.CompareTo((Person)obj) == 0); } public override int GetHashCode() { return base.GetHashCode(); } public static bool operator==(Person x, Person y) { return x.Equals(y); } public static bool operator !=(Person x, Person y) { return !x.Equals(y); } }
Jetzt kannst Du den ersten Codeauschnitt nochmals testen:
Person x = new Person();
Person y = new Person();
Console.WriteLine(x.Equals(y)); // immer wahr da zwar versch. Objekte, aber WertegleichheitSo könnte man auf die Schnelle sagen, ob zwei Objekte wertegleich sind (bitgleich, vereinfacht).
Es gibt aber auch intelligentere Verfahren, z.B. die Implementierung von INotifyPropertyChanged, IEditableObject und der IChangeTracking-Schnittstelle. So könntest Du in jedem Property-Setter automatisch IChangeTracking.IsChanged auf true setzen und nicht nur immer passiv wissen, ob sich dein Objekt geändert hat, sondern auch von diesem über die INotifyPropertyChanged-Schnittstelle erfahren, sobald eine Änderung eingetreten ist.
Gruß
Marce- Als Antwort markiert Robert BreitenhoferModerator Montag, 13. Februar 2012 10:38
-
Hi,
dafür gibt es bspw. das hier:
http://msdn.microsoft.com/de-de/library/bsc2ak47.aspx
Da wird IMHO gut erklärt, wie man mit Equals arbeitet und eine Vergleichsmethoden aufbauen kann.
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- Als Antwort vorgeschlagen Horizon_Net Mittwoch, 25. Januar 2012 10:25
- Als Antwort markiert Robert BreitenhoferModerator Montag, 13. Februar 2012 10:38
Alle Antworten
-
Hi,
dafür gibt es bspw. das hier:
http://msdn.microsoft.com/de-de/library/bsc2ak47.aspx
Da wird IMHO gut erklärt, wie man mit Equals arbeitet und eine Vergleichsmethoden aufbauen kann.
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- Als Antwort vorgeschlagen Horizon_Net Mittwoch, 25. Januar 2012 10:25
- Als Antwort markiert Robert BreitenhoferModerator Montag, 13. Februar 2012 10:38
-
Hallo,
Auf deine Frage gibt es keine eindeutige Antwort, da wir gar nichts von der Klasse wissen, die du instanziiert hast und die Du nun mit einer geklonten Instanz vergleichen möchtest. Wir wissen auch nicht, ob die geänderten Werte, die Du feststellen möchtest, nur Werte sind, die über öffentliche Member erreichbar sind, oder auch interne Werte (Zustand).
Darüber hinaus gibt es unterschiedliche Levels von Klonen: die flache Member-Kopie, bei der nur die Property-Werte auf eine neue Instanz übertragen werden (wie wir sie meist in IClonable-Implementationen finden) und es gibt noch die tiefe Kopie, die oft über binäre Serialisierung in ein MemoryStream erreicht wird.
Und es gibt die unterschiedlichsten Vergleichs-Arten. Und unterschiedliche Überschreibung von Object.Equals: Typen wie String oder Integer überschreiben die geerbte Methode und stellen fest, ob die Werte identisch sind, während die Basisimplementation ein simpler Verweisvergleich ist, der angibt, ob die Referenzen auf das gleiche Objekt verweisen.
Person x = new Person();
Person y = new Person();
Console.WriteLine(x.Equals(y)); // immer falsch (falls Equals nicht überschrieben wurde), da versch. Objekte
Egal ob Du im obigen Beispiel die gleichen Property-Werte einsetzt, die Objekte bleiben verschieden.Wenn es sich um eine eigene Klasse handelt, die Du beliebig verändern kannst, könntest Du einen schnellen binären Vergleich der Instanzen vornehmen, z.B.:
[Serializable] class Person : ICloneable, IComparable<Person>, IEquatable<Person> { public string FirstName { get; set; } public string LastName { get; set; } public object Clone() { return new Person { FirstName = FirstName, LastName = LastName }; } public int CompareTo(Person y) { BinaryFormatter formatter = new BinaryFormatter(); using (MemoryStream memoryStreamX = new MemoryStream()) { using (MemoryStream memoryStreamY = new MemoryStream()) { formatter.Serialize(memoryStreamX, this); formatter.Serialize(memoryStreamY, y); var binaryArrayX = memoryStreamX.GetBuffer(); var binaryArrayY = memoryStreamY.GetBuffer(); if (binaryArrayX.Length != binaryArrayY.Length) return binaryArrayX.Length.CompareTo(binaryArrayY.Length); for (int i = 0; i < binaryArrayX.Length; i++) if (binaryArrayX[i] != binaryArrayY[i]) return binaryArrayX[i].CompareTo(binaryArrayY[i]); } } return 0; } public bool Equals(Person other) { return (this.CompareTo(other) == 0); } public override bool Equals(object obj) { return (this.CompareTo((Person)obj) == 0); } public override int GetHashCode() { return base.GetHashCode(); } public static bool operator==(Person x, Person y) { return x.Equals(y); } public static bool operator !=(Person x, Person y) { return !x.Equals(y); } }
Jetzt kannst Du den ersten Codeauschnitt nochmals testen:
Person x = new Person();
Person y = new Person();
Console.WriteLine(x.Equals(y)); // immer wahr da zwar versch. Objekte, aber WertegleichheitSo könnte man auf die Schnelle sagen, ob zwei Objekte wertegleich sind (bitgleich, vereinfacht).
Es gibt aber auch intelligentere Verfahren, z.B. die Implementierung von INotifyPropertyChanged, IEditableObject und der IChangeTracking-Schnittstelle. So könntest Du in jedem Property-Setter automatisch IChangeTracking.IsChanged auf true setzen und nicht nur immer passiv wissen, ob sich dein Objekt geändert hat, sondern auch von diesem über die INotifyPropertyChanged-Schnittstelle erfahren, sobald eine Änderung eingetreten ist.
Gruß
Marce- Als Antwort markiert Robert BreitenhoferModerator Montag, 13. Februar 2012 10:38
-
Hallo umocomp1,
Ich gehe davon aus, dass die Antworten Dir weitergeholfen haben.
Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.Grüße,
Robert
Robert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.