如何调用base.base.GetHashCode()等二级基类方法

时间:2009-06-17 11:50:56

标签: c# inheritance

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

new B().GetHashCode()

这会溢出堆栈。如何从Object.GetHashCode()致电B.GetHashCode()

编辑:B现在继承自A

4 个答案:

答案 0 :(得分:19)

(编辑 - 误读问题)

如果您想获得原始object.GetHashCode()版本;你不能 - 至少,除非A通过以下方式提供它,否则不会:

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

(并B致电GetBaseHashCode())。

它溢出的原因是GetHashCode(显然)是虚拟的 - 如果你把它投射到object并不重要;它仍然从实际对象中最派生的实现开始,即B.GetHashCode()(因此爆炸)。

答案 1 :(得分:14)

您可以使用RuntimeHelpers.GetHashCode(object)获取对象的原始哈希码:

  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));
    }
  }

这会产生以下结果:

  

基本哈希码是:54267293
   A的哈希码:1
   A的原始哈希码:54267293

如果您查看Reflector中的RuntimeHelpers.GetHashCode(object),您会看到它调用内部静态方法object.InternalGetHashCode(object)。如果您想了解更多信息,请查看有关GetHashCode默认实现的this question

答案 2 :(得分:7)

我正在使用外部库,我也想调用base.base(因为在某些情况下会出现错误)。经过一些研究后,我遇到了这个页面http://www.rsdn.ru/forum/dotnet/475911.aspx

这很简单:使用要调用方法的基类定义委托,并将对象指针设置为* this(或您想要的对象)

所以,重要的代码是:

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();
    }

答案 3 :(得分:0)

如果您可以修改子子类的代码,那么您可以使用静态方法实现子子方法的功能。这个静态(公共)方法的第一个参数是类的对象。这样你就可以从任何地方调用它。

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);
    }
}