How to Detect If Type Is Another Generic Type

Testing if object is of generic type in C#

If you want to check if it's an instance of a generic type:

return list.GetType().IsGenericType;

If you want to check if it's a generic List<T>:

return list.GetType().GetGenericTypeDefinition() == typeof(List<>);

As Jon points out, this checks the exact type equivalence. Returning false doesn't necessarily mean list is List<T> returns false (i.e. the object cannot be assigned to a List<T> variable).

How To Detect If Type is Another Generic Type

The previously accepted answer is nice but it is wrong. Thankfully, the error is a small one. Checking for IEnumerable is not enough if you really want to know about the generic version of the interface; there are a lot of classes that implement only the nongeneric interface. I'll give the answer in a minute. First, though, I'd like to point out that the accepted answer is overly complicated, since the following code would achieve the same under the given circumstances:

if (items[key] is IEnumerable)

This does even more because it works for each item separately (and not on their common subclass, V).

Now, for the correct solution. This is a bit more complicated because we have to take the generic type IEnumerable`1 (that is, the type IEnumerable<> with one type parameter) and inject the right generic argument:

static bool IsGenericEnumerable(Type t) {
var genArgs = t.GetGenericArguments();
if (genArgs.Length == 1 &&
typeof(IEnumerable<>).MakeGenericType(genArgs).IsAssignableFrom(t))
return true;
else
return t.BaseType != null && IsGenericEnumerable(t.BaseType);
}

You can test the correctness of this code easily:

var xs = new List<string>();
var ys = new System.Collections.ArrayList();
Console.WriteLine(IsGenericEnumerable(xs.GetType()));
Console.WriteLine(IsGenericEnumerable(ys.GetType()));

yields:

True
False

Don't be overly concerned by the fact that this uses reflection. While it's true that this adds runtime overhead, so does the use of the is operator.

Of course the above code is awfully constrained and could be expanded into a more generally applicable method, IsAssignableToGenericType. The following implementation is slightly incorrect1 and I’ll leave it here for historic purposes only. Do not use it. Instead, James has provided an excellent, correct implementation in his answer.

public static bool IsAssignableToGenericType(Type givenType, Type genericType) {
var interfaceTypes = givenType.GetInterfaces();

foreach (var it in interfaceTypes)
if (it.IsGenericType)
if (it.GetGenericTypeDefinition() == genericType) return true;

Type baseType = givenType.BaseType;
if (baseType == null) return false;

return baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == genericType ||
IsAssignableToGenericType(baseType, genericType);
}

1 It fails when the genericType is the same as givenType; for the same reason, it fails for nullable types, i.e.

IsAssignableToGenericType(typeof(List<int>), typeof(List<>)) == false
IsAssignableToGenericType(typeof(int?), typeof(Nullable<>)) == false

I’ve created a gist with a comprehensive suite of test cases.

Determine if object is an instance of a generic base class, any generic type

The problem is that DrevidedC1 is not a sublcass of Class1<T>, it's a subclass of Class1<int>. Make sure you understand this subtle diference; Class1<T> is a open type (T can be anything, it hasn't been set) while DerivedC1 extends a closed type Class1<int> (it's not open in T anymore, T is set to int and only int). So when you do the following:

 typeof(DerivedC1).IsSubclassOf(typeof(Class1<>))

The answer is evidently false.

What you need to do is check if the generic type definition of DerivedC1's base type (think of it as the corresponding open generic type of Class1<int>) equals Class1<T> which it clearly does.

The correct code is therefore:

typeof(DerivedC1).BaseType.GetGenericTypeDefinition() == typeof(Class1<>));

Or better yet, as Matías Fidemraizer states in his answer:

typeof(DerivedC1).BaseType.GetGenericTypeDefinition().IsAssignableFrom(typeof(Class1<>)));

How to check if a generic type implements a specific type of generic interface in java?

Java implements erasure, so there's no way to tell on runtime if genericObject is an instance of Set<String> or not. The only way to guarantee this is to use bounds on your generics, or check all elements in the set.

Compile-time Generic Bounds

Using bounds checking, which will be checked at compile-time:

public <T extends SomeInterface> void genericMethod(Set<? extends T> tSet) {
// Do something with tSet here
}

Java 8

We can use streams in Java 8 to do this natively in a single line:

public <T> void genericMethod(T t) {
if (t instanceof Set<?>) {
Set<?> set = (Set<?>) t;
if (set.stream().allMatch(String.class:isInstance)) {
Set<String> strs = (Set<String>) set;
// Do something with strs here
}
}
}

Java 7 and older

With Java 7 and older, we need to use iteration and type checking:

public <T> void genericMethod(T t) {
Set<String> strs = new HashSet<String>();
Set<?> tAsSet;
if (t instanceof Set<?>) {
tAsSet = (Set<?>) t;
for (Object obj : tAsSet) {
if (obj instanceof String) {
strs.add((String) obj);
}
}
// Do something with strs here
} else {
// Throw an exception or log a warning or something.
}
}

Guava

As per Mark Peters' comment below, Guava also has methods that do this for you if you can add it to your project:

public <T> void genericMethod(T t) {
if (t instanceof Set<?>) {
Set<?> set = (Set<?>) t;
if (Iterables.all(set, Predicates.instanceOf(String.class))) {
Set<String> strs = (Set<String>) set;
// Do something with strs here
}
}
}

The statement, Iterables.all(set, Predicates.instanceOf(String.class)) is essentially the same thing as set instanceof Set<String>.

Check if object is of generic type with multiple type arguments

If you want to know whether the type is a generic InstantFeedbackCollectionViewModel you can use this code :

bool isInstantFeedbackCollectionViewModel = 
datagrid.ItemsSource.GetType().GetGenericTypeDefinition() ==
typeof(InstantFeedbackCollectionViewModel<,,>);

If you want to know whether the type inherits from a generic InstantFeedbackCollectionViewModel then see Check if a class is derived from a generic class.

Check if a class is generic type

From the Class<?> object you can check cls.getTypeParameters().

From a generic class you get a nonempty array of TypeVariable.

From a non-generic class you get an empty array.

E.g.

java.util.List.class.getTypeParameters()
TypeVariable[1] { E }
String.class.getTypeParameters()
TypeVariable[0] {}

How to determine if a type implements a specific generic interface type

By using the answer from TcKs it can also be done with the following LINQ query:

bool isBar = foo.GetType().GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IBar<>));

Check if a class is derived from a generic class

Try this code

static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
while (toCheck != null && toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}


Related Topics



Leave a reply



Submit