C# Vererbungsebene Frage.

roker002

Commander
Registriert
Dez. 2007
Beiträge
2.103
Wenn man von eine Klasse vererbt, sollte man base.MethodeProperty benutzen oder sollte man mit this.MethodeProperty Arbeit? Mir ist aufgefallen, dass beim base.IndexOf (wenn ich von einer BindingList erbe) der falscher index geliefert wird.

Natürlich habe ich Equals und GetHashCode überschrieben um den gültigen Vergleich zu haben.


Wieso habe ich immer den falschen Index bekommen, wenn ich base benutze und wieso bekomme ich den richtigen wenn ich this.IndexOf benutze? Der vergleich findet ja zwischen den Objekten in der Liste statt oder?
 
base ist doch der Aufruf der nichtstatischen methoden/properties/fields aus der "Basisklasse" von der man geerbt hat.
 
Uhi da sitzen aber einige Grundlagen gewaltig nicht.
Base ist die Referenz auf das Basisobjekt, hat weder was mit statischen noch nichtstatischen Methoden zu tuen.
this ist die Referenz auf das aktuelle Objekt.

@roker: Woher sollen wir wissen warum du den falschen Index erhälst wenn du uns nicht zeigst was du gemacht hast.
Vielleicht sind deine Methoden gerade so implementiert das sie eben durch den Vergleich diesen angeblich falschen Index erhalten ;)
 
Tja es ist nichts spektakuläres!

Code:
int index = IndexOf(item);
//int index = base.IndexOf(item);


///Hier aus dem Object die zu der Liste hinzugefügt wird. Equals funktioniert gut, da man 
///eine Klasse hat die eindeutig ist und deren ID (aus der DB) auch für diese Klasse 
///eindeutig sind
        public override bool Equals(object obj)
        {
            if(obj == null)
                return false;

            if (!obj.GetType().Equals(this.GetType()))
                return false;

            int h1 = this.GetHashCode();
            int h2 = obj.GetHashCode();


            if (h1 == h2)
                return true;

            return false;
        }

        public override int GetHashCode()
        {
            return (this.id.GetHashCode() | this.TableName.GetHashCode());
        }

Was wäre am sichersten? Base oder this? Ich verstehe schon dass bei base sich um die Referenz der Basisklasse (von der man erbt) sich handelt. Solange ja man keine einzelnen Methode überschrieben hat, sollte eigentlich BASE vollkommen geeignet sein oder?
 
Zuletzt bearbeitet:
Puhh also erstmal solltest du deine Equals-Methode auf Fordermann bringen.
Besser wäre es wenn du das IEquatable<T> Interface überschreibst weil das Typsicherer ist.
Weiterhin ist es etwas sinnlos die null-Prüfung von "obj" nach dem aufruf von GetHashcode zu machen :D
Dann rufst du einfach die von object überschrieben Equals-Methode mit deiner von IEquatable implementieren auf. Um da mal etwas Ordnung reinzubringen.
Hast du mal überprüft das wenn "this.Equals(otherObject)" true zurückliefert auch "this.GetHashCode() == other.GetHashCode()" true ist? Das ist nämlich extrem wichtig.

Und mit "Sicherheit" hat der Aufruf von base oder this nichts zu tuen, sonder mit Sinnhaftigkeit. base wird nur aufgerufen wenn du die wirklich was von der Basisimplementation brauchst, ansonsten nicht.
 
upsala... hehe stimmt, du hast ja recht... obj.GetHashCode() ist sinnlos! So jetzt korregiert. Danke

Mit IEquatable wollte ich auch in der erste Instanz machen. Aber wie soll ich in eine abstrakte Klasse T definieren? Von der abstrakte Klasse erben min 8 verschiedene Klassen.

Ja this.GetHashCode() wird auch mit obj.GetHashCode() gefunden. Da habe ich vorher auch selbst debuggt.

Base benutze ich ja auch nur dann wenn ich die Basisimplementierung auch brauche. Es ist klar, wenn ich irgendwas überschrieben habe, benutze ich this. Es wird halt übersichtlicher, ob ich eigene Implementierung benutze oder die von der Basisklasse nehme.
 
Der vergleich zwischen den Objecten in der BindingList findet aber trotzdem über den Equals(Object) statt.

Wann wird eigentlich IEquatable verwendet?
 
tjas, das heißt ich kann es wieder ausbauen? :D
An sich brauche ich eigentlich keinen Equals, da ich keine objekte in dem Sinne vergleichen muss!
 
Dann brauchst du auch kein GetHashCode. Weil diese 3 Sachen eigentlich immer zusammen auftreten müssen, weil sie gegenseitige Abhängigkeiten haben. Implementierst du eins der 3 brauchst du alle anderen auch.
 
also ich weiss, wenn man equals überschreibt sollte man auch hashcode überschreiben. Wo liegt der zusammenhang mit IEquatable?
 
Lies doch bitte nochmal meinen Beitrag zwei über dir.
IEquatable ist ein generisches Interface um Typsicherheit zu gewährleisten und wenn du die geschenkt bekommst warum nicht einfach benutzen?
In der Equals-Methode welche nicht generisch ist, rufst du dann einfach nur noch die generische auf.

Code:
public bool Equals(object o)
{
  return this.Equals(o as Klasse);
}
public bool Equals(Klasse k)
{
   return this.ID == k.ID;
}
 
Der Beispiel ist einleuchtend... aber hat man dann nicht Bedenken wegen den Typen des Object o?

Code:
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            if (!obj.GetType().Equals(this.GetType()))
                return false;

            return this.Equals(obj as Klasse);
        }
Du meintest:
Implementierst du eins der 3 brauchst du alle anderen auch.
Das heißt, man muss auch HashCode auch überschreiben? Irgendwie wiedersprüchlich zu der aussagen davor.

  1. GetHashCode
  2. Equals(Object o)
  3. Equals(Klasse k)
GetHashCode()

Sorry vielleicht bin ich jetzt bisschen nervig, aber es interessiert mich halt einfach um zukünfitg fehler zu vermeiden.
 
Also eigentlich ist die Reihenfolge wie folgt.
Ich zeig dir mal ein Beispiel aus einem meiner Projekte wo man das besser sieht:
Code:
partial class ImagePoint : IComparable<ImagePoint>, IEquatable<ImagePoint>
    {
        public int CompareTo(ImagePoint other)
        {
            if (other == null)
                return -1;

            return this.Name.CompareTo(other.Name);
        }

        public bool Equals(ImagePoint other)
        {
            if (other == null)
                return false;

            return this.Name == other.Name;
        }

        public override bool Equals(object obj)
        {
            var o = (obj as ImagePoint);

            if (o == null)
                return false;

            return (o.Name == this.Name);
        }

        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }

        public static bool operator ==(ImagePoint a, ImagePoint b)
        {
            // source: http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx
            // If both are null, or both are same instance, return true.
            if (ReferenceEquals(a, b))
            {
                return true;
            }

            // If one is null, but not both, return false.
            if (((object)a == null) || ((object)b == null))
            {
                return false;
            }

            // Return true if the fields match:
            return (a.Name == b.Name);
        }

        public static bool operator !=(ImagePoint a, ImagePoint b)
        {
            return !(a == b);
        }
    }

Wenn du Equals überschreibst, musst du auch, GetHashCode und die jeweiligen logischen Operatoren überschreiben. IComparable wurde hier noch für einen Vergleich implementiert.
IEquatable, wird nur deswegen mit dazu Implementiert weil es wie gesagt eine Typsicherer Variante von Equals ist, den aufruf aus der überschrieben object-Equals Methode leitet man somit nur noch an die Generische Variante weiter.
 
Zurück
Oben