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 » Gemeinschaft » .NET-Komponenten und C#-Snippets » Equals - Eigene Klasse um die Funktion Equals erweitern.
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Equals - Eigene Klasse um die Funktion Equals erweitern.

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

Dabei seit: 23.08.2013
Beiträge: 12
Entwicklungsumgebung: VS2019
Herkunft: Siegburg


RX8 ist offline

Equals - Eigene Klasse um die Funktion Equals erweitern.

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

Beschreibung:
Die Erweiterung basiert auf einem Dateivergleich. Die Dateien werden aber nicht auf einen Datenspeicher geschrieben sondern nur temporär in einen XML-Memorystream.

Aber das Snippet ist nicht generell zu verwenden. Es funktioniert nicht wenn z.B. in einer Klasse Elemente vom serialisieren ausgeschlossen sind, oder wenn sie als privat deklariert sind.

Wenn man aber die Ursprungsklasse so wie auch gespeichert wird, also ohne die ausgeschlossenen Parameter, mit der geänderten Klasse vergleichen will (was ja wohl die Regel ist) funktioniert es sehr wohl.

Bitte die nachfolgende Diskussion beachten.

XML-Code:
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
            <Title>Equals</Title>
            <Author>Klaus Ruttkowski</Author>
            <Description>Compares the object (class) "this" to another object (class).</Description>
            <HelpUrl>
      </HelpUrl>
            <Shortcut>
      </Shortcut>
        </Header>
        <Snippet>
            <Imports>
                <Import>
                    <Namespace>System.Collections.Generic</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Text</Namespace>
                </Import>
                <Import>
                    <Namespace>System.IO</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Xml.Serialization</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Xml</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Drawing</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Linq</Namespace>
                </Import>
            </Imports>
            <Code Language="csharp" Delimiter="$"><[CDATA[
#region Equals
// Calls
// this.Equals(ComparisonObject);
//
public bool Equals<T>(T value)
{
    int file1byte;
         int file2byte;

         MemoryStream memoryStreamX = new MemoryStream();
         MemoryStream memoryStreamY = new MemoryStream();

         var settings = new System.Xml.XmlWriterSettings { Encoding = Encoding.UTF8, CheckCharacters = false, NewLineHandling = NewLineHandling.None, };
         using (XmlWriter xmlWriter = XmlWriter.Create(memoryStreamX, settings))
         {

             XmlSerializer serializer = new XmlSerializer(typeof(T));

                    serializer.Serialize(xmlWriter, this);
         }
         using (XmlWriter xmlWriter = XmlWriter.Create(memoryStreamY, settings))
         {

             XmlSerializer serializer = new XmlSerializer(typeof(T));

                    serializer.Serialize(xmlWriter, value);
         }
         // Check the file sizes. If they are not the same, the files
         // are not the same.
         if (memoryStreamX.Length != memoryStreamY.Length)
         {
             // Return false to indicate files are different
                    return false;
         }

         // Read and compare a byte from each file until either a
         // non-matching set of bytes is found or until the end of
         // file1 is reached.
         do
         {
             // Read one byte from each file.
             file1byte = memoryStreamX.ReadByte();
                    file2byte = memoryStreamY.ReadByte();
         }
         while ((file1byte == file2byte) && (file1byte != -1));

         // Return the success of the comparison. "file1byte" is
         // equal to "file2byte" at this point only if the files are
         // the same.
         return ((file1byte - file2byte) == 0);
}
#endregion
]]></Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Schlagwörter: Equals, Class, Vergleich

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von RX8 am 08.01.2020 09:35.

06.01.2020 10:28 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.989
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

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

Da der Vergleich auf Serialisierung basiert, wird er unter bestimmten Voraussetzungen fälschlich true liefern, obwohl die Objekte verschieden sind, oder umgekehrt.

LaTino
06.01.2020 11:50 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MarsStein MarsStein ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 3.140
Entwicklungsumgebung: VS 2013, MonoDevelop
Herkunft: Trier -> München


MarsStein ist offline

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

Hallo,

Abgesehen von dem was LaTino bereits geschrieben hat, auch die generische Implementierung:

C#-Code:
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlWriter, this);

Das dürfte gewaltig rumpeln, wenn this nicht gerade vom Typ T ist.

Wenn man schon eine Equals-Methode zur Verfügung stellt, sollte wenigstens dafür georgt sein das sie auch sicher ist.
Meiner Ansicht nach sollte dann zumindest auch IEquatable<T> implementieren.

Generell sollten Snippets universell und sicher einsetzbar sein - das ist hier nicht der Fall.

Gruß, MarsStein

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von MarsStein am 06.01.2020 12:40.

06.01.2020 12:24 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
RX8 RX8 ist männlich
myCSharp.de-Mitglied

Dabei seit: 23.08.2013
Beiträge: 12
Entwicklungsumgebung: VS2019
Herkunft: Siegburg

Themenstarter Thema begonnen von RX8

RX8 ist offline

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

Zitat von LaTino:
Da der Vergleich auf Serialisierung basiert, wird er unter bestimmten Voraussetzungen fälschlich true liefern, obwohl die Objekte verschieden sind, oder umgekehrt.

LaTino

Hallo LaTino

Das Snippet ist als Erweiterung der zu vergleichenden Klasse gedacht und funktioniert bei mir einwandfrei. Wenn ich also das Objekt mit dem Ursprungsinhalt mit einem Objekt der selben Klasse aber mit abgeänderten Inhalt darüber vergleiche, warum soll das mal so und mal anders funktionieren?

Hallo MarsStein

Unter den oben genannten Bedingungen ist der Typ<T> doch bekannt?

Wenn ihr aber der einhelligen Meinung seid, aufgrund eurer tieferen Kenntnis der Sprache c#, das Snippet sei ungeeignet für eine Veröffentlichung, löschen ich es selbstverständlich.
06.01.2020 13:39 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.989
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

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

Falls nicht klar ist, was ich meine, ein Beispiel. Es gibt, ohne zu übertreiben, Dutzende Möglichkeiten, Vergleiche über Serialisierung kaputtzumachen. Nicht empfehlenswert. Gäbe es eine generische Möglichkeit, komplexe Klassen zu vergleichen, bräuchte man IEquatable/IComparable nicht.

C#-Code:
public class TestEquals
{
[Fact]
  public void TestEquals()
  {
    Example expected = new Example {ExampleString = "example"};
    Example actual = new InheritedExample { ExampleString = "example" };

    Assert.True(expected.Equals(actual)); // Fehler.
    Assert.True(actual.Equals(expected)); // Fehler.
  }
}

public class InheritedExample : Example { [XmlIgnore] public override string ExampleString { get; set; } }

[XmlInclude(typeof(InheritedExample))]
public class Example
{
  public virtual string ExampleString { get; set; }

  public bool Equals<T>(T value)
  {
  /* ...snippet hier. */
  }
}

(EDIT: Zeilenumbrüche korrigiert)

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von LaTino am 06.01.2020 13:43.

06.01.2020 13:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MarsStein MarsStein ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 3.140
Entwicklungsumgebung: VS 2013, MonoDevelop
Herkunft: Trier -> München


MarsStein ist offline

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

Hallo,

Zitat:
Unter den oben genannten Bedingungen ist der Typ<T> doch bekannt?

Inwiefern?
Was hindert mich daran, so etwas zu schreiben:

C#-Code:
public class MyClass
{
    public bool Equals<T>(T value)
    {
         //...
    }
}

// und dann so aufzurufen:

MyClass c = new MyClass();

if(c.Equals<int>(42)) // statt int könnte ich hier auch JEDEN ANDEREN TYPEN einsetzen.
{
}

Main Rat: Schau Dir mal IEquatable<T> an, und verwende es.

Gruß, MarsStein

Gruß, MarsStein
06.01.2020 13:50 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
RX8 RX8 ist männlich
myCSharp.de-Mitglied

Dabei seit: 23.08.2013
Beiträge: 12
Entwicklungsumgebung: VS2019
Herkunft: Siegburg

Themenstarter Thema begonnen von RX8

RX8 ist offline

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

Ok, ich gehe natürlich davon aus, dass kein Objekt eines anderen Tys verwendet wird. Für meinen speziellen Fall hatte ich eine einfache Möglichkeit gesucht ein komplexes Objekt zu vergleichen und es funktioniert ja auch. Aber ich sehe ein das mein Snippet nicht allgemein zu gebrauchen ist.
Kann ich den Beitrag löschen, kann der Admin ihn löschen, oder wie soll ich verfahren?

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von RX8 am 06.01.2020 14:17.

06.01.2020 14:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.989
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

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

Ich für meinen Teil sehe keinen Grund, das nicht stehen zu lassen. Serialisierung für Vergleiche zu nutzen, liegt ja relativ nahe, der Gedankengang ist meistens etwa so:

- Vergleich von Hand zu schreiben nervt
- Vergleich mit Reflection über die öffentlichen Member funktioniert
- feststellen, dass beim Serialisieren auch mit Reflection die öffentlichen Member ausgewertet werden
--> direkt Zurückgreifen auf Serialisierung

Die Idee haben wahrscheinlich die meisten Entwickler mal irgendwann ;). Und im Normalfall geht das auch, der Teufel steckt nur leider im Detail. Ich finde es nicht verkehrt, den Teufel hier mal zu skizzieren und das auch im Forum zu lassen. Muss aber ein Admin entscheiden (eventuell verschieben?).

LaTino
06.01.2020 15:28 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.325
Herkunft: Leipzig


MrSparkle ist online

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

Ich fände es schon in Ordnung, das hier stehen zu lassen. Es kann ja jeder Entwickler selbst Anpassungen vornehmen.

Man sollte aber am besten gleich im Eingangsposting Hinweise auf die Einschränkungen geben. Die Verwendung von XML als Serialisierungsformat bringt ja auch noch weitere Einschränkungen mit sich, z.B. werden nur öffentliche Eigenschaften serialisiert, und "Circular References" (Kreisreferenzen?, wie heißt das auf Deutsch?) verursachen eine Exception.

Eine binäre Serialisierung würde hier Abhife schaffen, und meist auch den eigentlichen Vergleich beschleunigen.
06.01.2020 17:07 Beiträge des Benutzers | zu Buddylist hinzufügen
gfoidl gfoidl ist männlich
myCSharp.de-Team

avatar-2894.jpg


Dabei seit: 07.06.2009
Beiträge: 6.631
Entwicklungsumgebung: VS 2019
Herkunft: Waidring


gfoidl ist offline

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

Hallo MrSparkle,

Zitat:
"Circular References" (Kreisreferenzen?, wie heißt das auf Deutsch?)

zirkuläre Abhängigkeit

mfG Gü
06.01.2020 18:04 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 2 Monate.
Der letzte Beitrag ist älter als 2 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 31.03.2020 22:17