2010-10-11 55 views
7

我想實現一個通用的C#類,它看起來大致如下:我可以指定一個C#類型參數只能是一個接口類型嗎?

abstract class Foobar<T> : AbstractBase, T 
{ ... } 

失敗的原因是C#只允許類型的基類之後是接口,所以未來我試試這個:

abstract class Foobar<T> : AbstractBase, T where T : interface 
{ ... } 

但後來我發現C#不允許這種形式的類型約束。只允許使用where T : structwhere T : class

我該如何規定類型參數只能是接口類型?

+3

你想達到什麼目的?我無法真正想到需要這種約束的情況。 – jalf 2010-10-11 11:06:48

回答

6

基本上,你不能。

您可以對特定接口進行約束,但不是所有接口的通用接口。所以你可以限制爲IEnumerable爲例,但不是的任何接口。

你究竟需要什麼?

+0

我注意到從Foobar 派生的所有類也最終實現T.我想我可以通過將'implements Blah'從我的派生類移動到基類Foobar上來強制執行這種情況。 – pauldoo 2010-10-11 14:16:01

0

失敗的原因是C#只允許類型的基類之後是接口

這個限制是由於在C#中缺少多重繼承的。多重繼承可以通過使用接口來近似,因爲重寫方法是明確的。一個類只能擴展一個其他類,但可以實現多個接口。這裏的技巧是實現類必須爲方法定義主體,以便實現特定於調用哪個方法。

使用限制T的位置可以應用於一個類或幾個接口。您不能將範圍限制爲幾個類別。

1

我相信你誤解了where T : structwhere T : class的含義。

一個通用type constraint像這意味着T必須是值類型或分別一引用類型

然而,接口的目的是定義合同,這是一個完全不同的概念相比值類型與引用類型的語義。

因此像where T : interface這樣的限制是沒有意義的。

如果你想知道更多,我建議你閱讀C#編程指南類型約束:

Constraints on Type Parameters (C# Programming Guide)

+0

作爲接口類型的約束是有意義的,如果有語言特性可用於這種類型和只有這些類型。例如,如果可以定義一個'Wrapper :T其中T:interface(Foo)',這個類將定義一個類型爲'T'的字段'Foo'的語義並且明確地實現每個通過調用'Foo.m',接口'T'的成員'm'。如果CLR提供了必要的功能,那麼這樣一個通用的設施即使在支持CLR的情況下也不適用於類,但對於接口可能非常有用。 – supercat 2012-06-29 18:05:18

4

與該代碼真正的問題是,你是從類型參數繼承。

試圖編譯

abstract class Foobar<T> : T { ... } 

仍然會失敗:錯誤CS0689:無法從「T」派生,因爲它是一個類型參數。

我認爲這至少在抽象類的情況下是完全合理的,我也想要這個特性,但是C#編譯器不會讓你這樣做。

+0

+1提到問題的核心(從類型參數派生)。 – Frank 2010-10-11 12:57:27

相關問題