Let's say we have a collection of types:
var types = new[]
{
typeof(IEnumerable<int>),
typeof(ICollection<int>),
typeof(Stack<int>),
typeof(IList<int>),
typeof(int[])
};
If you think about type hierarchy, you can imagine that:
IEnumerable<int>
|
ICollection<int>
/ \
Stack<int> IList<int>
\
int[]
This isn't my actual problem, but it gets down to the following question:
Given a collection of types that all represent some tree (with a single root), how can I get a subcollection that contains those types that were leaves in the original collection.
So, for the collection above, the leaves would be Stack<int>
and int[]
.
How to do that in an elegant way? Any help will be greatly appreciated!
In my problem, I am dealing with actual types that derive from each other, creating a tree. For example, I can have:
class Root {}
class LeftChild : Root {}
class RightChild : Root {}
class LeftChildChild : LeftChild {}
In which case I would like to yield LeftChildChild
and RightChild
.
It seems to me that Type.IsAssignableFrom
is your friend here. You want types that aren't assignable from any of the other types in the set:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var types = new[]
{
typeof(IEnumerable<int>),
typeof(ICollection<int>),
typeof(Stack<int>),
typeof(IList<int>),
typeof(int[])
};
var leaves = types.Where(candidate =>
!types.Any(t => t != candidate && candidate.IsAssignableFrom(t)));
Console.WriteLine(string.Join(Environment.NewLine, leaves));
}
}
See more on this question at Stackoverflow