2009-12-07 46 views
2

我剛開始學習泛型,並使用它們來重構我的代碼中相當複雜的部分(我只使用c#一段時間,但我在其他語言方面頗有經驗)。鍵入變量保存受約束泛型類的實例

我有我的類擴展基類的繼承結構。在基類中,我實現了大部分功能。但我希望能夠將這些兒童類與他們的兄弟姐妹的實例相關聯。

下面是一些相關的代碼的簡化:

class ParentClass<T> 
    where T : ParentClass<T>, new() 
{ 

    public static T Create() 
    { 
     return new T(); 
    } 

    private object joinedItem; 

    public void Join<TJoinee>(TJoinee item) 
     where TJoinee : ParentClass<TJoinee>, new() 
    { 
     joinedItem = item; 
    } 

} 

class ChildOne : ParentClass<ChildOne> 
{ 
} 

class ChildTwo : ParentClass<ChildTwo> 
{ 
} 

有了這個代碼在地方,我可以這樣做:

var a = ChildOne.Create(); 
a.Join(new ChildTwo()); 

的問題是,我需要鍵入joinedItem爲對象,當我真的想要鍵入它作爲ParentClass<Something>。是否可以規定一個更具體的類型joinedItem?或者我只是可怕地濫用語言,應該採取一種完全不同的方法?

回答

3

您能否從ParentClass<T>中提取不依賴於T的接口?這樣可以將joinedItem鍵入界面。

這似乎是,只要你可以採取它看起來像你試圖做的事情(加入ParentClass<T>實例到ParentClass<U>實例)。

如果ParentClass<T>接口不依賴於T,那麼在不知道T的情況下,將很難找到比對象更有用的接口。

+0

嗯 - 我可能可以去接口路由...我會看看實際的代碼,看看是否有任何地方會掉下來... – vitch 2009-12-07 15:44:22

+0

但即使有*沒有*在接口是獨立於T的,你說的只是爲了代碼的意圖和可讀性的清晰性。即使它只是一個標記接口,編譯器仍然會驗證你不會做不可能的強制轉換(即,你可以將一個'object'向下轉換爲'string',但是不能將'IJoinable'向下轉換爲'string' - 'string'不執行'IJoinable'。) – 2009-12-07 18:39:12

+0

好點Eamon – philsquared 2009-12-07 21:59:18

1

這裏的核心問題是不可能表達變量必須是XYZ<_>類型的概念 - 具有任意類型參數。

可以表達的參數,那麼你只需要添加約束(如你這樣做),但你不能給變量(至少不無添加變量類型的類型參數列表,這很可能在語法上很醜陋)。

所以,如果你需要表達的XYZ<_>概念對任何類型_,你需要明確地表示這一概念作爲一種類型(比如IXYZ),並確保所有XYZ<_> : IXYZ的實際上是從繼承。通常,最靈活的方法是通過一個接口,但抽象基類也可以。

不幸的是,類型類一般不是泛型的一部分;-)。

+0

謝謝你的回答。當你說「沒有將變量類型添加到類型參數列表」時,你的意思是在類級別添加類型參數嗎? – vitch 2009-12-07 15:52:26

+0

在你的情況,是的,你需要在類級別添加類型參數,因爲你想專門化一個類的變量 - 我不建議這樣做,這可能會使你的代碼更容易維護。然而,我所說的只是你使用的構造,Join方法有一個約束的泛型類型參數TJoinee。無論如何 - 如果有疑問,請使用接口來指定您需要的行爲;這可能更容易和更靈活(因爲一個類可以實現大量的接口)。 – 2009-12-07 18:34:46

+0

感謝您的澄清。我去接口路線,似乎都工作得很好! – vitch 2009-12-08 12:25:47