2010-10-11 49 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

相关问题