If you have an instance of a generic type but for some reason don't know the specific type, you might want to determine the generic arguments that were used to create this instance.
Let's say someone created an instance of List<T>
like that and passes it to a method:
var myList = new List<int>();
ShowGenericArguments(myList);
where ShowGenericArguments
has this signature:
public void ShowGenericArguments(object o)
so at compile time you don't have any idea what generic arguments have been used to create o
. Reflection provides a lot of methods to inspect generic types. At first, we can determine if the type of o
is a generic type at all:
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsGenericType) return;
...
Type.IsGenericType
returns true
if the type is a generic type and false
if not.
But this is not all we want to know. List<>
itself is a generic type, too. But we only want to examine instances of specific constructed generic types. A constructed generic type is for example a List<int>
that has a specific type argument for all its generic parameters.
The Type
class provides two more properties, IsConstructedGenericType
and IsGenericTypeDefinition
, to distinguish these constructed generic types from generic type definitions:
typeof(List<>).IsGenericType // true
typeof(List<>).IsGenericTypeDefinition // true
typeof(List<>).IsConstructedGenericType// false
typeof(List<int>).IsGenericType // true
typeof(List<int>).IsGenericTypeDefinition // false
typeof(List<int>).IsConstructedGenericType// true
To enumerate the generic arguments of an instance, we can use the GetGenericArguments()
method that returns an Type
array containing the generic type arguments:
public void ShowGenericArguments(object o)
{
if (o == null) return;
Type t = o.GetType();
if (!t.IsConstructedGenericType) return;
foreach(Type genericTypeArgument in t.GetGenericArguments())
Console.WriteLine(genericTypeArgument.Name);
}
So the call from above (ShowGenericArguments(myList)
) results in this output:
Int32