簡體   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