[英]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
類是所有類的最終基類 。 所以它是我程序中A
和B
的基類,也是A
作為B
的基類。 所以B
現在有兩個基類,一個是A
,另一個是Object
。 我覆蓋一個方法GetHashCode()
的Object
類中的類A
和B
這兩者。 但是在B
類中, base.GetHashCode()
方法返回類A
的GetHashCode()
方法的返回值。 但我想從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.