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
Nunit VS. Visual Studio 2008's Test Projects for Unit Testing
Better Way to Query a Page of Data and Get Total Count in Entity Framework 4.1
How to Set Up HTML/Email Templates with ASP.NET
How to Wait for Async Method to Complete
Singleton by Jon Skeet Clarification
How Does Transactionscope Roll Back Transactions
What's the Difference Between Iequatable and Just Overriding Object.Equals()
Why Use Try {} Finally {} with an Empty Try Block
What Is the Point of Lookup<Tkey, Telement>
What Is the "Cost" of .Net Reflection
How Do C# Events Work Behind the Scenes
Check If the Current User Is Administrator
Query Extremely Slow in Code But Fast in Ssms
How to Return a Custom Http Status Code from a Wcf Rest Method