简体   繁体   English

Generics 和铸件

[英]Generics and casting

class B : A {}
class Sub<T> where T:A
{
//...
}

I want to store Sub instances in a collection.我想将 Sub 实例存储在集合中。

var c = new List<Sub<A>>();
c.Add(new Sub<B>()); //doesn't work

However, to get it to actually work, I have to declare an interface and store instances of that interface.但是,要让它真正工作,我必须声明一个接口并存储该接口的实例。

interface IBase
{
    void DoStuff(A a);
}

var c = new List<IBase>();
c.Add(new Sub<B>()); //works

Is there a more elegant way of doing this?有没有更优雅的方式来做到这一点?

No. Instantiations of a generic type with different type arguments are completely unrelated.不。具有不同类型 arguments 的泛型类型的实例化完全不相关。 The only way you can get them in the same list is by having the list use a common non-generic base class or interface, as you did here.将它们放在同一个列表中的唯一方法是让列表使用通用的非通用基础 class 或接口,就像您在此处所做的那样。

You can achieve an approximation of what you want by using a covariant generic interface:您可以通过使用协变通用接口来实现您想要的近似值:

class A { }
class B : A { }

interface ISub<out T> where T : A
{
    // Members go here
}

class Sub<T> : ISub<T> where T : A
{
    // Members go here.
}

Which can be used as follows:可以按如下方式使用:

List<ISub<A>> list = new List<ISub<A>>();
list.Add(new Sub<B>());

You need an interface because only interfaces can have covariant or contravariant type parameters.您需要一个接口,因为只有接口才能具有协变或逆变类型参数。

Depends on how you use it, but perhaps you could use a covariant interface for Sub :取决于您如何使用它,但也许您可以为Sub使用协变接口:

interface ISub<out T> where T:A
{
}

Then ISub<B> can be implicitly converted(via a reference conversion) to ISub<A>然后ISub<B>可以隐式转换(通过引用转换)到ISub<A>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM