2011-09-20 59 views
5

不幸的是,我找不到導致我這個問題的原始項目。這可能會讓這個問題更具體一些。繼承最衍生類型的抽象類

編輯:我發現,原來的項目,我已經看到了這一點:與一個具體的實現http://mews.codeplex.com/SourceControl/changeset/view/63120#1054567http://mews.codeplex.com/SourceControl/changeset/view/63120#1054606

可以說我有一個抽象類的具體實現,做有用的東西,如:

abstract class AbstractClass 
{ 
    public virtual int ConvertNumber(string number) 
    { 
     string preparedNumber = Prepare(number); 
     int result = StringToInt32(number); 
     return result; 
    } 

    protected abstract string Prepare(string number); 

    protected virtual int StringToInt32(string number) 
    { 
     return Convert.ToInt32(number); 
    } 
} 

sealed class ConcreteClass : AbstractClass 
{ 
    protected override string Prepare(string number) 
    { 
     return number.Trim(); 
    } 

    public override int ConvertNumber(string number) 
    { 
     return base.ConvertNumber(number); 
    } 
} 

這是最基本的了。現在,在代碼中我已經看到了網絡筆者從最派生類型繼承抽象類實現繼承,e.g上:

abstract class AbstractGenericClass<TGenericClass> 
    where TGenericClass : AbstractGenericClass<TGenericClass> 
{ 
    public virtual int ConvertNumber(string number) 
    { 
     string preparedNumber = Prepare(number); 
     int result = StringToInt32(number); 
     return result; 
    } 

    protected abstract string Prepare(string number); 

    protected int StringToInt32(string number) 
    { 
     return Convert.ToInt32(number); 
    } 
} 

sealed class ConcreteGenericClass : AbstractGenericClass<ConcreteGenericClass> 
{ 
    protected override string Prepare(string number) 
    { 
     return number.Trim(); 
    } 

    public override int ConvertNumber(string number) 
    { 
     return base.ConvertNumber(number); 
    } 
} 

現在爲什麼會一個做這樣的事情?我非常隱約地記得,這是一種在性能方面大量使用ATL的技術(某種方式調用具體成員實現而不使用vtable?)我對這部分不太確定。

我檢查了兩種情況下生成的IL,它們完全一樣。

誰能向我解釋這一點?

+0

我不認爲你的代碼的第一部分編譯。 'public override int ConvertNumber(string number)''但是沒有這樣的方法可以在基類型中覆蓋。 –

+0

我猜不能這樣做? http://pastebin.com/BgpuKYb7 – Zenwalker

+1

@DannyChen:你的權利,我已經改變了一些代碼的標記,我現在修復它。問題仍然存在 – Polity

回答

4

這是C++中所謂的奇怪循環模板模式的C#版本。這有點奇怪,我個人試圖避免它。這很有用,但我覺得它比有用的更困惑。

請參見我的文章的詳細信息:

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

+0

謝謝Eric!這真的讓我的大腦陷入混亂。幸運的是,你的文章大聲而清晰地解釋了它。 – Polity

+1

@Eric Lippert - 我傾向於喜歡這種模式,以允許祖先類擁有可以使用/返回後代類實例的成員。我期望OP的示例代碼具有這樣的方法或屬性。然而,唯一的缺點是,如果例如'class X:AbstractGenericClass ',並且您有'class Y:AbstractGenericClass ',則可以打破該模式。我希望C#有一個「this」約束來防止這種情況 - 即抽象類A 其中T:this,A ' - 只要你聲明具體類,那麼通用參數必須是它自己。 **微推**埃裏克。 – Enigmativity

+0

@Enigmativity:的確,我討論了你在我鏈接的文章中找到的缺點。你真的需要一個「thistype」構造來使模式起作用。你可以在Haskell中做這樣的事情,但不能在C#中做;這樣做需要對CLR類型系統進行一些非常重要的工作,所以不可能很快發生。 –