简体   繁体   中英

Generics and casting

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

I want to store Sub instances in a collection.

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. 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.

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 :

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

Then ISub<B> can be implicitly converted(via a reference conversion) to ISub<A>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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