C# 如何调用像base.base.GetHashCode()这样的二级基类方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1006530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:21:20  来源:igfitidea点击:

How to call a second-level base class method like base.base.GetHashCode()

c#inheritance

提问by usr

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

new B().GetHashCode()

this overflows the stack. How can I call Object.GetHashCode()from B.GetHashCode()?

这会溢出堆栈。我怎样才能Object.GetHashCode()从打电话B.GetHashCode()

edit: Bnow inherits from A.

编辑:B现在继承自A.

采纳答案by Marc Gravell

(edit - misread question)

(编辑 - 误读问题)

If you want to get the original object.GetHashCode()version; you can't - at least, not unless Amakes it available via something like:

如果您想获得原始object.GetHashCode()版本;你不能 - 至少,除非A通过以下方式使其可用:

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

(and have Bcall GetBaseHashCode()).

(并有B电话GetBaseHashCode())。

The reason it overflows is that GetHashCodeis (obviously) virtual - it doesn't matter if you cast it to object; it still starts at the most-derived implementation in the actual object, i.e. B.GetHashCode()(hence the explosion).

它溢出的原因GetHashCode是(显然)是虚拟的 - 如果你将它转换为object; 它仍然从实际对象中最衍生的实现开始,即B.GetHashCode()(因此爆炸)。

回答by Igal Tabachnik

You can use RuntimeHelpers.GetHashCode(object)to get the original hash code of the object:

您可以使用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));
    }
  }

This produces the following result:

这会产生以下结果:

base hashcode is: 54267293
A's hashcode: 1
A's original hashcode: 54267293

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

If you take a look at RuntimeHelpers.GetHashCode(object)in Reflector, you'll see that it calls the internal static method object.InternalGetHashCode(object). If you'd like to know more, have a look at this questionregarding the default implementation of GetHashCode.

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

回答by Sauleil

I'm using an external library and I wanted to call the base.base also (because of a bug in certain case). After some research I came across this page http://www.rsdn.ru/forum/dotnet/475911.aspx

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

It's quite simple: You define a delegate using the base class you want to call your method and set the object pointer to *this (or the object you want)

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

So, the important code is:

所以,重要的代码是:

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

回答by schoetbi

If you can modify the code of the sub-sub class then you can implement the functionality of the sub-sub-method with a static method. This static (public) method has as first parameter an object of the class. That way you can call it from everywhere.

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

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