29 Stimmen

Wie ruft man eine Basisklassenmethode der zweiten Ebene wie base.base.GetHashCode() auf?

class A
{
    public override int GetHashCode()
    {
        return 1;
    }
}
class B : A
{
    public override int GetHashCode()
    {
        return ((object)this).GetHashCode();
    }
}

new B().GetHashCode()

der Stapel überläuft. Wie kann ich aufrufen Object.GetHashCode() de B.GetHashCode() ?

bearbeiten: B erbt nun von A .

21voto

Marc Gravell Punkte 970173

(Bearbeiten - Frage falsch gelesen)

Wenn Sie das Original erhalten möchten object.GetHashCode() Version; das können Sie nicht - zumindest nicht, wenn A macht es über etwas wie verfügbar:

protected int GetBaseHashCode() { return base.GetHashCode();}

(und haben B aufrufen GetBaseHashCode() ).

Der Grund für den Überlauf ist, dass GetHashCode ist (offensichtlich) virtuell - es spielt keine Rolle, ob Sie es an object ; es beginnt immer noch mit der am weitesten abgeleiteten Implementierung im eigentlichen Objekt, d. h. B.GetHashCode() (daher die Explosion).

14voto

Igal Tabachnik Punkte 30660

Sie können verwenden RuntimeHelpers.GetHashCode(object) um den ursprünglichen Hash-Code des Objekts zu erhalten:

  class A
  {
    public override int GetHashCode()
    {
      Console.WriteLine("base hashcode is: " + base.GetHashCode());

      return 1;
    }
  }

  class Program
  {
    public static void Main(string[] args)
    {
      A a = new A();

      Console.WriteLine("A's hashcode: " + a.GetHashCode());

      Console.WriteLine("A's original hashcode: " + RuntimeHelpers.GetHashCode(a));
    }
  }

Dies führt zu folgendem Ergebnis:

Basis-Hashcode ist: 54267293
Der Hashcode von A: 1
den ursprünglichen Hashcode von A: 54267293

Werfen Sie einen Blick auf RuntimeHelpers.GetHashCode(object) in Reflector, werden Sie sehen, dass es die interne statische Methode object.InternalGetHashCode(object) . Wenn Sie mehr wissen möchten, schauen Sie unter diese Frage bezüglich der Standardimplementierung von GetHashCode.

7voto

Sauleil Punkte 2513

Ich verwende eine externe Bibliothek und ich wollte die base.base auch aufrufen (wegen eines Fehlers in bestimmten Fall). Nach einigen Recherchen bin ich auf diese Seite gestoßen http://www.rsdn.ru/forum/dotnet/475911.aspx

Es ist ganz einfach: Sie definieren einen Delegaten mit der Basisklasse, die Ihre Methode aufrufen soll, und setzen den Objektzeiger auf *this (oder das gewünschte Objekt)

Der wichtige Code lautet also:

public delegate void MD();

public void Test() {
        // A is the base class you want to call the method.
        A a = new A();
        // Create your delegate using the method name "M" with the instance 'a' of the base class
        MD am = (MD)Delegate.CreateDelegate(typeof(MD), a, "M");
        // Get the target of the delegate and set it to your object (this in most case)
        am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance BindingFlags.NonPublic).SetValue(am, this);
        // call the method using the delegate.
        am();
    }

0voto

schoetbi Punkte 10841

Wenn Sie den Code der Sub-Sub-Klasse ändern können, können Sie die Funktionalität der Sub-Sub-Methode mit einer statischen Methode implementieren. Diese statische (öffentliche) Methode hat als ersten Parameter ein Objekt der Klasse. Auf diese Weise können Sie sie von überall aus aufrufen.

class A
{
    public static int CalcHashCode(A obj)
    {
        return 1;
    }

    public override int GetHashCode()
    {
        return CalcHashCode(this);
    }
}
class B : A
{
    public override int GetHashCode()
    {
        return A.CalcHashCode(this);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X