如果对象属于泛型类型,我想执行测试。我尝试了以下但没有成功:
public bool Test()
{
List<int> list = new List<int>();
return list.GetType() == typeof(List<>);
}
我做错了什么以及如何进行此测试?
答案 0 :(得分:171)
如果要检查它是否是泛型类型的实例:
return list.GetType().IsGenericType;
如果您想检查它是否为通用List<T>
:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
Jon指出,这会检查确切的类型等价。返回false
并不一定意味着list is List<T>
返回false
(即无法将对象分配给List<T>
变量)。
答案 1 :(得分:79)
我假设您不仅想知道类型是否是通用的,而且如果对象是特定泛型类型的实例,而不知道类型参数。
不幸的是,它并不是非常简单。如果泛型类型是一个类(在这种情况下就是这样),那也不算太糟糕,但接口更难。这是一个类的代码:
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>
{
}
}
编辑:正如评论中所述,这可能适用于接口:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
我有一种潜在的怀疑,可能会有一些尴尬的边缘情况,但我找不到它现在失败。
答案 2 :(得分:6)
您可以使用动态althougth来使用更短的代码,这可能比纯反射更慢:
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();
答案 3 :(得分:5)
这是我最喜欢的两种扩展方法,涵盖泛型类型检查的大多数边缘情况:
适用于:
过载会导致出现过多的情况。如果返回true,则为特定泛型类型(请参阅样本的单元测试):
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;
}
}
这是一个演示(基本)功能的测试:
[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);
}
答案 4 :(得分:0)
return list.GetType().IsGenericType;