是否可以在.net中创建通用约束类型的集合?

时间:2010-01-20 07:13:41

标签: .net generics collections constraints

这样的事情可能吗?

Dim l As New List(Of T As Type Where GetType(BaseClass).IsAssignableFrom(T))

注意,我的集合将是类型的集合,而不是T类型的对象 - 我知道这是可能的。

ETA:

到目前为止我得到的答案是预期的 - 我认为不可能。

我想要解决的问题是为什么以下内容可以在编译时解决,但不是我的例子:

Dim l as New List(Of T As BassClass)

检查基本上是否相同?

6 个答案:

答案 0 :(得分:2)

您可以对集合实施运行时强制约束,如下所示:

public class ConstrainedTypeCollection<TBaseType> : Collection<Type>
{
    protected override void InsertItem(int index, Type item)
    {
        if (!typeof(TBaseType).IsAssignableFrom(item))
            throw new ArgumentException("The type is incompatible.", "item");

        base.InsertItem(index, item);
    }

    protected override void SetItem(int index, Type item)
    {
        if (!typeof(TBaseType).IsAssignableFrom(item))
            throw new ArgumentException("The type is incompatible.", "item");

        base.SetItem(index, item);
    }
}

修改:只要您调用通用Add<T>()Contains<T>()和{{1},您也可以执行以下操作并获得完整的编译时类型安全性方法。

Remove<T>()

答案 1 :(得分:2)

检查不一样 - 在您的第一个示例中,您要求编译器调用“IsAssignableFrom”方法,然后根据结果执行某些操作。在第二个例子中,您要求编译器的静态类型检查器做一些工作。

通常,编译器在编译期间不会调用任意代码。

另外,请记住,对泛型的任何类型约束都必须嵌入到程序集元数据中。而且,您不能将任意代码放在泛型类型约束中。

答案 2 :(得分:0)

不,不可能。 Type in generic需要在编译时解决。

答案 3 :(得分:0)

我认为在编译时静态检查是不可能的。但您可以覆盖Add,AddRange和this []以在运行时检查添加的元素。

答案 4 :(得分:0)

要做到这一点,你需要创建Type(Of TBase)类,然后列出它们。 然后你可以尝试保证Type(Of TBase)是静态正确的。

但是在大​​多数情况下,你需要从CLR Type创建Type(Of TBase),它只能动态保证。

答案 5 :(得分:0)

可以在不使用Reflection的情况下实现一系列遵循多个通用约束的东西,但它非常狡猾。添加到集合中的每个项都必须用类对象包装。如果集合应该将事物限制为I1I2,则每个项目都将包含在类型为TI1和{的通用类的实例中{1}}(约束为I2),它实现了通用类型T:I1,I2I1的接口。集合本身将保存该接口类型的引用。

如果有人有兴趣,我可以发布更多细节。