How do I create a list of objects that inherit from the same generic class with varying types?
I've spent a few hours on and off trying to find an answer to this, I'm probably having trouble with wording the question correctly, which doesn't help. Essentially, I have an abstract class:
public abstract class GenericType<T>
{ ... }
And a bunch of classes that inherit from it:
public class AType: GenericType<A>
{ ... }
public class BType: GenericType<B>
{ ... }
...
Lastly, I have another class that wants to contain a list of things that inherit from GenericType, regardless of the value of T, i.e. Atypes, BTypes and so on.
My first attempts were to use List<GenericType>
and List<GenericType<Object>>
开发者_JS百科but niether's given me any joy.
Any tips on how I should be going about this? Much thanks!
How do I create a generic List of objects that are constrained to inherit from the same generic class constructed with different type arguments?
That's not possible in the C# type system; you can only make a list of an actual type, not of a "type pattern" like "List<U>
where U must be Foo<T>
for some unspecified T".
To see why it is impossible, let's hypothetically suppose that it was possible. We'll annotate the "type pattern" as a question mark:
class Stack<T> { ... }
...
List<Stack<?>> listOfStacks = new List<Stack<?>>();
listOfStacks.Add(new Stack<int>());
listOfStacks.Add(new Stack<Giraffe>());
Ok, great. Now what are you going to do with the list of stacks? You can't safely do anything with the stack that involves the type parameter of the stack:
listOfStacks[0].Push("hello");
That should fail at compile time because the stack in slot zero is a stack of ints, not strings. How can the compiler know that? The compiler cannot know that. By allowing this feature, you essentially break the ability of the compiler to type-check your program.
To answer "how do I do this thing which is impossible?" it is helpful to know why you want to do the impossible thing. Instead of trying to do this impossible thing tell us what you are really trying to do and see if anyone can solve the real problem.
So, if I understand correctly, you want something like this:
List<GenericType>
Which can contain any instance of AType
, BType
, etc. You simply do this by making GenericType<T>
itself a subclass of GenericType
:
public class GenericType { }
public class GenericType<T> : GenericType { }
public class AType : GenericType<int> { }
public class BType : GenericType<int> { }
You can then stick any instance into a List<GenericType>
.
If GenericType<T>
implemented a non-generic interface IAmNotGeneric
, then both AType
s and BType
s could be added to a List<IAmNotGeneric>
.
public abstract class GenericType<T> : IAmNotGeneric
The same principle could be applied with a non-generic abstract base class.
public abstract class GenericType<T> : NonGenericType
Did you mean a list with an instance of each derived type?
Assembly.GetExecutingAssembly().GetTypes
.Where(type => type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(GenericType<>))
.ToList().
.ForEach(type => list.Add(Activator.CreateInstance(type)));
精彩评论