2011-03-25 201 views
5

我在圖書館三類用途:C#泛型類型

public abstract class Base<TFirst, TSecond> 
{ 
    public Base() 
    { 
     // actions with ID and Data of TFirst and TSecond 
    } 
} 

public abstract class First<TFirstID, TFirstData> 
{ 
    public TFirstID ID {get; set;} 
    public TFirstData Data {get; set;} 
} 

public abstract class Second<TSecondID, TSecondData> 
{ 
    public TSecondID ID {get; set;} 
    public TSecondData Data {get; set;} 
} 

我怎麼可以指定T第一必須從第一個繼承和TSecond必須從第二繼承,不使用泛型類型爲基礎ID和數據?

像這樣:

public abstract class Base<TFirst, TSecond> 
    where TFirst : First // without generic-types 
... 

編輯: 在班級第一,第二我用TFirstID和TSecondID的性質。在課堂上我使用這個屬性。

+0

請問您能澄清一下這個問題嗎?一壘? – foson 2011-03-25 15:49:52

+0

你的意思是你**不要**想在哪裏TFirst:第一個'我認爲你不能這樣做,我認爲haskell允許這樣的事情,不確定。 – gideon 2011-03-25 15:52:11

+0

玻色子:不,先不繼承基地 – 2011-03-25 15:53:52

回答

1

如果他們依賴於這些項目的簽名,這可能會很棘手。我可能會說創建一個沒有類型簽名的接口或抽象基礎。接口更有可能。

2

通常在這樣的情況下,我會建一個基類(非通用)的First<TFirstID, TFirstData>從,所以得出:

public abstract class First{} 

public abstract class First<TFirstID, TFirstData> 
    : First 
{ 
} 

然後你就可以把一個where TFirst : First到你的宣言。這並不完美,但如果你小心的話,它會有效。但是這可能很棘手,取決於你想要完成的事情 - 你失去了限制類型的所有通用性。

6

有沒有辦法可以比通過引入一個平行的類層次不geherics,做一些運行時檢查做到這一點其他:

public abstract class Base<TFirst, TSecond> 
    where TFirst : First 
{ 
    static Base() 
    { 
     if(!typeof(TFirst).IsGenericType || 
      typeof(TFirst).GetGenericTypeDefinition() != typeof(First<,>)) 
      throw new ArgumentException("TFirst"); 
    } 
} 

public abstract class First { } 
public abstract class First<TFirstID, TFirstData> : First 
{ 
} 

或者,你可以用一個標記接口(IFirst)取代First

運行時檢查是可能的,因爲每個closed generic type都會調用靜態構造函數。

+0

+1非常有趣!但是,他實際上不能將通用的'TFirst'限制爲**成爲** First ',它仍然可以是從「abstract First」繼承的任何東西。我認爲這可能是一個反模式沒有? – gideon 2011-03-25 15:53:15

2

一個解決辦法是有第一和第二實施本身不依賴於泛型類型參數的接口:

public interface IFirst 
{ 
} 

public abstract class First<TFirstID, TFirstData> : IFirst 
{ 
} 

然後確保在鹼的類型參數必須使用IFirst

public abstract class Base<TFirst, TSecond> 
    where TFirst : IFirst 
+0

這是避免使用實際類的唯一方法,同時允許使用泛型類型作爲Object以外的其他類型。 – KeithS 2011-03-25 15:55:03

0

就是這樣,如果可能的話,指定允許編譯器捕獲Base基本參數的無效用法的泛型類型約束。

如果出於某種原因根本不能使用泛型類型約束,唯一強制執行類型檢查的方法是將運行時檢查添加到邏輯中,如果泛型是創建指定無效泛型類型:

public abstract class Base<TFirst, TSecond> 
{ 
    public Base() 
    { 
     if(!typeof(TFirst).IsAssignableFrom(typeof(First)) 
      throw new InvalidOperationException("TFirst must derive from First."); 
     if(!typeof(TSecond).IsAssignableFrom(typeof(Second)) 
      throw new InvalidOperationException("TSecond must derive from Second."); 
    } 
} 

上述代碼是嚴重的代碼異味。泛型的要點是允許一個類使用許多不同的內部類,同時允許編譯器確保使用的參數類型能夠使泛型類與它們一起工作。此外,您還必須能夠引用First和Second的命名空間(我認爲這是您不能將它們用作泛型類型參數的原因)。

+0

我認爲你的代碼應該是這樣的:'typeof(TFirst).IsAssignableFrom(typeof(First <,>))' – 2011-03-25 15:56:06

+0

也許,但我的觀點是整件事情是代碼味道;應該以幾乎任何成本實施泛型類型限制以避免這樣的事情。 – KeithS 2011-03-25 15:57:43

+0

當然,我同意你的意見。但是,如果您發佈代碼,請確保它已編譯。否則,不要將它發佈在第一位。 – 2011-03-25 15:59:38