这可能吗:c# 带有约束的类型集合,还是泛型类型的集合?

发布于 2024-09-04 07:01:04 字数 318 浏览 3 评论 0原文

我试图将类型存储在集合中,以便稍后可以实例化集合中类型的对象。但我不确定如何最好地做到这一点。

到目前为止我所拥有的:

List<Type> list = new List<Type>();
list.Add(typeof(MyClass));
var obj = (MyClass)Activator.CreateInstance(list[0]);

我希望对 Type 有一些约束,或者更好的是,只是集合中的通用类型而不是实例化的 Type 对象。这可能吗?

I'm trying to store types in a collection, so that i can later instantiate objects of the types in the collection. But I'm not sure how to do this the best way.

What i have so far:

List<Type> list = new List<Type>();
list.Add(typeof(MyClass));
var obj = (MyClass)Activator.CreateInstance(list[0]);

I would like to have some constrains on the Type, or better yet, just a generic type in the collection instead of an instantiated Type object. Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

寻找我们的幸福 2024-09-11 07:01:04

这不是通用集合约束的工作方式。

泛型约束限制哪些类型对于实例化泛型类型是合法的。有几种不同类型的约束,但常见的约束将泛型参数限制为继承或成为给定类型的实例,或者是实现特定接口(或接口集)的类型。

类型,另一方面,是一个类,描述有关应用程序或其库中的类型的信息。特定种类的类型不会继承或扩展 Type - 相反,每种可用类型都有不同的 Type 实例。您不能使用通用约束来控制可以将哪些 Type 实例添加到您的集合中。

如果没有更多关于如何“限制”集合中的信息的详细信息,很难说您应该采取什么路线。例如,如果您只想确保只有唯一类型 (不存储重复项),这可以通过 HashSet(而不是列表)来实现。但是,如果您想要更专业的东西 - 例如限制可以添加到某些类型子集的 Type 实例,那么您可能需要实现自己的集合,并在添加/插入中实现 gaurd 逻辑方法。

That's not how generic collection constraints work.

Generic constraints restrict which types are legal for instantiating a generic type. There are several different kinds of constraints, but the common ones limit a generic parameter to either inherit or be an instance of a given type, or be a type that implements a particular interface (or set of interfaces).

Type, on the other hand, is a class that describes information about a type in your application or one of it's libraries. Specific kinds of types don't inherit or extend Type - rather there is a different instance of Type for each type available. You cannot use generic constraints to control which instances of Type may be added to your collection.

Without more detail about how you want to "constrain" the information in the collection, it's hard to say what route you should take. For example, if all you want to do is ensure that only unique types (no dups) are stored, that can be achieved with a HashSet (rather than a list). But if you want something more specialized - like limiting the Type instances that can be added to some subset of types, then you will likely need to implement your own collection, and implement gaurd logic in the Add/Insert methods.

全部不再 2024-09-11 07:01:04

在这个特定的场景中,我们似乎有一个“工厂”模式,我们将限制调用激活器的方法,例如

private readonly List<Type> _supportedTypes = new List<Type> ();
public void RegisterSupportedType<T> () where T : SomeConstraintType
{
    _supportedTypes.Add (typeof (T));
}

// if we do not know the type, but somehow know an index to type
public object Create (int supportedTypeIndex)
{
    object untyped = Activator.
        CreateInstance (_supportedTypes[supportedTypeIndex]);
    return untyped;
}

// if we know instance type\subtype (eg interface) and know an index
public T Create<T> (int supportedTypeIndex)
{
    T typed = default (T);
    object untyped = Create (supportedTypeIndex);
    if (!(untyped is T))
    {
        // throw meaningful exception :)
    }
    typed = (T)(untyped);
    return typed;
}

另一种选择是创建一个受约束的Type

public class ConstrainedType<T> 
{
    public Type Type { get; private set; }
    public ConstrainedType (Type type)
    {
        // may have this backward, would have to fact check before
        // rolling out to prod ;)
        if (!typeof (T).IsAssignableFrom (type))
        {
            // throw meaningful exception!
        }
        Type = type;
    }
}

List<ConstrainedType<SomeTypeConstraint>> list = 
    new List<ConstrainedType<SomeTypeConstraint>> ();

// will throw meaningful exception if MyClass is not 
// SomeTypeConstraint or a sub class
list.Add (new ConstrainedType (typeof (MyClass)));

SomeTypeConstraint baseType = 
    (SomeTypeConstraint)(Activator.CreateInstance(list[0].Type));

In this particular scenario, where it seems we have a "factory" pattern, we would constrain the method invoking the activator, such as

private readonly List<Type> _supportedTypes = new List<Type> ();
public void RegisterSupportedType<T> () where T : SomeConstraintType
{
    _supportedTypes.Add (typeof (T));
}

// if we do not know the type, but somehow know an index to type
public object Create (int supportedTypeIndex)
{
    object untyped = Activator.
        CreateInstance (_supportedTypes[supportedTypeIndex]);
    return untyped;
}

// if we know instance type\subtype (eg interface) and know an index
public T Create<T> (int supportedTypeIndex)
{
    T typed = default (T);
    object untyped = Create (supportedTypeIndex);
    if (!(untyped is T))
    {
        // throw meaningful exception :)
    }
    typed = (T)(untyped);
    return typed;
}

An alternative, is to create a constrained Type

public class ConstrainedType<T> 
{
    public Type Type { get; private set; }
    public ConstrainedType (Type type)
    {
        // may have this backward, would have to fact check before
        // rolling out to prod ;)
        if (!typeof (T).IsAssignableFrom (type))
        {
            // throw meaningful exception!
        }
        Type = type;
    }
}

List<ConstrainedType<SomeTypeConstraint>> list = 
    new List<ConstrainedType<SomeTypeConstraint>> ();

// will throw meaningful exception if MyClass is not 
// SomeTypeConstraint or a sub class
list.Add (new ConstrainedType (typeof (MyClass)));

SomeTypeConstraint baseType = 
    (SomeTypeConstraint)(Activator.CreateInstance(list[0].Type));
女中豪杰 2024-09-11 07:01:04

Jon,

如果您使用 CodeContracts,您可能需要许多已知类型。代码分析将标记对您的集合的任何无效类型调用。

public class TypeCollection : List<Type>
{
    public TypeCollection()
    {
    }

    public new void Add(Type type)
    {
        Contract.Requires(type == typeof(string) || type == typeof(Stream));
        base.Add(type);
    }
}

public class TestCollection
{
    public void Test()
    {
        TypeCollection collection = new TypeCollection();
        // This gets compile time warning:
        collection.Add(typeof(int));
    }
}

但是,如果您提前知道类型,那么在枚举中指定所有类型并为您想要支持的类型创建创建有效枚举的集合可能更有意义。

Jon,

If you are using CodeContracts, you could require a number of known types. The code analysis would flag any calls to your collection with invalid types.

public class TypeCollection : List<Type>
{
    public TypeCollection()
    {
    }

    public new void Add(Type type)
    {
        Contract.Requires(type == typeof(string) || type == typeof(Stream));
        base.Add(type);
    }
}

public class TestCollection
{
    public void Test()
    {
        TypeCollection collection = new TypeCollection();
        // This gets compile time warning:
        collection.Add(typeof(int));
    }
}

But, if you know the types in advance, it might make more sense to specify them all in an enum and create a collection of valid enums for the type creation you want to support.

尝蛊 2024-09-11 07:01:04

第一种方法(看起来很愚蠢但很安全):
(在 List || 上创建一个包装器实现 IList)并在 .Add 方法中检查 .Exists(item)。

first way(seems stupid but it is safe):
(create a wrapper over the List || implement IList) and check .Exists(item) in the .Add Method.

雨巷深深 2024-09-11 07:01:04

如果您要实现自己的集合,则可以使用泛型类型约束:

public class MyList<T> 
    where T : IMyConstraint

If you were to implement your own collection, you could use generic type constraints:

public class MyList<T> 
    where T : IMyConstraint
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文