0Day Forums
Testing if object is of generic type in C# - Printable Version

+- 0Day Forums (https://0day.red)
+-- Forum: Coding (https://0day.red/Forum-Coding)
+--- Forum: C# (https://0day.red/Forum-C)
+--- Thread: Testing if object is of generic type in C# (/Thread-Testing-if-object-is-of-generic-type-in-C)



Testing if object is of generic type in C# - tilliehzkggalvz - 07-24-2023

I would like to perform a test if an object is of a generic type. I've tried the following without success:

public bool Test()
{
List<int> list = new List<int>();
return list.GetType() == typeof(List<>);
}

What am I doing wrong and how do I perform this test?


RE: Testing if object is of generic type in C# - bacalao730607 - 07-24-2023

return list.GetType().IsGenericType;


RE: Testing if object is of generic type in C# - Drbuttonhook4 - 07-24-2023

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).


RE: Testing if object is of generic type in C# - Sirlied10 - 07-24-2023

I assume that you don't just want to know if the type is generic, but if an object is an instance of a particular generic type, without knowing the type arguments.

It's not terribly simple, unfortunately. It's not too bad if the generic type is a class (as it is in this case) but it's harder for interfaces. Here's the code for a class:

using System;
using System.Collections.Generic;
using System.Reflection;

class Test
{
static bool IsInstanceOfGenericType(Type genericType, object instance)
{
Type type = instance.GetType();
while (type != null)
{
if (type.IsGenericType &&
type.GetGenericTypeDefinition() == genericType)
{
return true;
}
type = type.BaseType;
}
return false;
}

static void Main(string[] args)
{
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new List<string>()));
// False
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new string[0]));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList()));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList<int>()));
}

class SubList : List<string>
{
}

class SubList<T> : List<T>
{
}
}

EDIT: As noted in comments, this may work for interfaces:

foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}

I have a sneaking suspicion there may be some awkward edge cases around this, but I can't find one it fails for right now.


RE: Testing if object is of generic type in C# - defenselesseseejvyokm - 07-24-2023

You can use shorter code using dynamic althougth this may be slower than pure reflection:

public static class Extension
{
public static bool IsGenericList(this object o)
{
return IsGeneric((dynamic)o);
}

public static bool IsGeneric<T>(List<T> o)
{
return true;
}

public static bool IsGeneric( object o)
{
return false;
}
}



var l = new List<int>();
l.IsGenericList().Should().BeTrue();

var o = new object();
o.IsGenericList().Should().BeFalse();



RE: Testing if object is of generic type in C# - almirabyus - 07-24-2023

These are my two favorite extension methods that cover most edge cases of generic type checking:

Works with:

- Multiple (generic) interfaces
- Multiple (generic) base classes
- Has an overload that will 'out' the specific generic type if it returns true (see unit test for samples):

public static bool IsOfGenericType(this Type typeToCheck, Type genericType)
{
Type concreteType;
return typeToCheck.IsOfGenericType(genericType, out concreteType);
}

public static bool IsOfGenericType(this Type typeToCheck, Type genericType, out Type concreteGenericType)
{
while (true)
{
concreteGenericType = null;

if (genericType == null)
throw new ArgumentNullException(nameof(genericType));

if (!genericType.IsGenericTypeDefinition)
throw new ArgumentException("The definition needs to be a GenericTypeDefinition", nameof(genericType));

if (typeToCheck == null || typeToCheck == typeof(object))
return false;

if (typeToCheck == genericType)
{
concreteGenericType = typeToCheck;
return true;
}

if ((typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck) == genericType)
{
concreteGenericType = typeToCheck;
return true;
}

if (genericType.IsInterface)
foreach (var i in typeToCheck.GetInterfaces())
if (i.IsOfGenericType(genericType, out concreteGenericType))
return true;

typeToCheck = typeToCheck.BaseType;
}
}

Here's a test to demonstrate the (basic) functionality:


[Test]
public void SimpleGenericInterfaces()
{
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>)));
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>)));

Type concreteType;
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>), out concreteType));
Assert.AreEqual(typeof(IEnumerable<string>), concreteType);

Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>), out concreteType));
Assert.AreEqual(typeof(IQueryable<string>), concreteType);


}