In one general collection, only one type of element will be known . Just as List<int> knows that its element is int , List<T> knows that its element is T
So, if you know that all of your trees will have the same type, but you do not know which , you need to abstract from this type:
class MyTreeHandler<T> { public List<Tree<T>> myListOfTrees = new List<Tree<T>>(); }
and "here you go." Of course, this will NOT work when trying to put heterogeneous trees on this list, since T one type of element .
So, since collections of type List know only one type of their element, before you can put heterogeneous objects in one common list / collection, you should find a “common denominator” for all of them.
The simplest common denominator is object , but of course it is. Thus, the most dumb and always working approach:
List<object>
and you can put all the Trees there.
But, of course, you didn’t want to hear that either. It just shows you the total value.
What is the common denominator of your trees? As you introduced, no. Of course, they are Trees<T> aka Tree``1 (there should be one return move, but I don’t know how to write it here), but remember that, with very few cases, you cannot use the non-parameterized type Tree<> in c #. And you cannot use Tree<T> without pointing T to something. And after you define it, Tree<T1> and Tree<T2> will be considered as two separate class hierarchies, unless T1 == T2 or if you do not use some in/out dispersion specifiers (e.g. IEnumerable<out> therefore IEnumerable<Kangaroo> matters >). I assume that you want mixed variance, therefore not an option. But if you want your tree to be only input or output, use the co / contravariance specifiers immediately!
So, let's leave generics and their deviations. To provide a C # comprehensible language / compiler, you need to enter something more .. basic.
A common abstract base other than object , some common interface . No matter what you think is the least dirty.
When I really had to mix and store generic files of a different type, I usually introduced a simple dual interface:
public interface IMyThing
Now I can use every thing for general IMyThing and store them as a mixed, impersonal List<IMyThing> . Thanks to the explicit implementation of the interface, I will not see any “untyped” members unless I drop them, so other T-aware will look as usual.
But, when I have to mix types, I can now apply them to a common impersonal interface, and thanks to the interface I will still have access to operations / properties. Assuming I somehow guarantee that the arguments will depend on the correct T. But I can always check the TypeParam and process it manually.
So pure trouble. Be that as it may, note that IEnumerable<T> and IEnumerable do the same!
Screaming for dynamic , but in fact, without dynamic (i.e.. .Net 3.5 platform without DLR?), There are few opportunities for other solutions.