繁体   English   中英

C#中的多重继承问题

[英]Multiple inheritance problem in C#

在我阅读帖子时,我想到了这个问题为什么C#不支持多重继承? 来自MSDN博客

首先看下面的代码:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class A
    {
        int num;
        public A()
        {
            num = 0;
        }
        public A(int x)
        {
            num = x;
        }
        public override int GetHashCode()
        {
            return num + base.GetHashCode();
        }
    }
    class B : A
    {
        int num;
        public B()
        {
            num = 0;
        }
        public B(int x)
        {
            num = x;
        }
        public override int GetHashCode()
        {
            return num + base.GetHashCode();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            B b = new B();
            Console.Write(a.GetHashCode() + " " + b.GetHashCode());
            Console.Read();
        }
    }
}

Object类是所有类的最终基类 所以它是我程序中AB的基类,也是A作为B的基类。 所以B现在有两个基类,一个是A ,另一个是Object 我覆盖一个方法GetHashCode()Object中的类AB这两者。 但是在B类中, base.GetHashCode()方法返回类AGetHashCode()方法的返回值。 但我想从Object类中获取此值。 我怎么能得到它?

B只有一个基类,即A A有一个基类,那就是object 没有多重继承; object只能由尚未从其他东西继承的类继承。

如果你仍然认为你需要调用object.GetHashCode() ,那么在如何调用(非虚拟)虚拟方法的原始实现的问题中有一个非常hacky的解决方法吗?

您可以在A类中编写一个受保护的实例方法,该方法从Object公开GetHashCode() 然后在B类中调用该受保护的方法。

没有B类只有一个基类,A类。

要理解,A级真的应该写成:

class A : Object

但由于这是必需的,因此可以不予考虑。

是的,这根本不涉及多重继承(顺便说一句,我错过了私有继承而不是多重继承)。 这个问题也是一个非常可怕的想法。

如果你控制了A级,那么罚款:

class A
{
    /*elide the stuff you already have*/
    protected int GetBaseHashCode()
    {
        return base.GetHashCode();
    }
}
class A : B
{
    /*elide stuff already in example*/
    public override int GetHashCode()
    {
        return num + GetBaseHashCode();
    }
}

如果你不:

public class B : A
{
    private static readonly DynamicMethod GRANDPARENT_GET_HASH_CODE;
    static B()
    {
        MethodInfo gpGHC = typeof(object).GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Instance);

        GRANDPARENT_GET_HASH_CODE = new DynamicMethod("grandParentGHC", typeof(int), new Type[] { typeof(object) }, typeof(object));
        ILGenerator il = GRANDPARENT_GET_HASH_CODE.GetILGenerator();
        il.Emit(OpCodes.Ldarg, 0);
        il.EmitCall(OpCodes.Call, gpGHC, null);
        il.Emit(OpCodes.Ret);
    }
    private int num;
    public B()
    {
        num = 0;
    }
    public B(int x)
    {
        num = x;
    }
    public override int GetHashCode()
    {
        return num + (int)GRANDPARENT_GET_HASH_CODE.Invoke(null, new object[]{this});
    }
}

坦率地说,我会把这些代码放在“让我们再也不说它”的范畴内。 我认为这与一些更一般的原则有关,因为这里的哈希码无论如何都是无用的,但我不确定那个更一般的原则是什么。 当然,当某些东西被隐藏起来导致我们想要得到的类时,它有时会很烦人,但是当相反的情况发生时会更糟。

回到VB6时代,那种语言的编码人员往往不得不做一些令人讨厌的事情,包括获取用于虚拟调用查找的v表的内存地址,改变内存保护,然后手动调整存储在那里的字节,因为在“保护”用户免受实现细节的影响时,他们将一些重要的东西远离它们(如果没有这种技术,你就无法创建枚举器,只能将其传递给其他对象)。

谢天谢地,我们在C#中没有受到“保护”。 如果我必须像上面给出的一个真实项目的答案那样编写代码,那么我晚上需要喝几杯才能恢复。

获取基础Object类的哈希与方法的目的无关。 GetHashCode()是根据对象的特定类型和状态生成唯一(尽可能)的标识值。

GetHashCode()方法使用默认的散列算法,可用于确定实例标识和唯一性,但不保证唯一性。 默认算法使用对象的状态来生成哈希。

更多信息: http//msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

我担心你将正常继承与多重继承混合在一起。 多继承meand你有3个类A是B和C的子类,但B既不是C的子类,也不是C的子类。

正常继承确实允许链接,就像A是B的子类,它是C的子类。如果你调用方法,它可以遍历类并检查调用哪个方法(实际上它不会逐个检查类)。 这里B是A的子类,它是Object的子类。 对象碰巧有(虚拟)方法GetHashCode - 通过在子类中重载它。 隐藏了Object方法,并且(不带技巧)无法使用。

您应该考虑调用Object.GetHashCode()的替代方法。 这就是为什么( 来自MSDN Library ):

GetHashCode方法的默认实现不保证不同对象的唯一返回值。 此外,.NET Framework不保证GetHashCode方法的默认实现,并且它返回的值在不同版本的.NET Framework之间是相同的。 因此,此方法的默认实现不得用作散列目的的唯一对象标识符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM