Jawaban:
Jika Anda ingin memeriksa apakah ini merupakan instance dari tipe generik:
return list.GetType().IsGenericType;
Jika Anda ingin memeriksa apakah itu generik List<T>
:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
Seperti yang ditunjukkan oleh Jon, ini memeriksa kesetaraan tipe persisnya. Kembali false
tidak selalu berarti list is List<T>
pengembalian false
(yaitu objek tidak dapat ditugaskan ke List<T>
variabel).
Saya berasumsi bahwa Anda tidak hanya ingin tahu apakah tipe itu generik, tetapi jika suatu objek adalah instance dari tipe generik tertentu, tanpa mengetahui argumen tipe.
Sayangnya, ini tidak terlalu sederhana. Tidak terlalu buruk jika tipe generiknya adalah kelas (seperti dalam kasus ini) tetapi lebih sulit untuk antarmuka. Berikut kode untuk kelas:
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: Seperti disebutkan dalam komentar, ini dapat berfungsi untuk antarmuka:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
Saya memiliki kecurigaan yang menyelinap mungkin ada beberapa kasus tepi canggung di sekitar ini, tetapi saya tidak dapat menemukan satu itu gagal untuk saat ini.
List<T>
dalam beberapa bentuk atau lainnya. Jika Anda menyertakan antarmuka, itu sangat rumit.
IsInstanceOfGenericType
dengan panggilan ke IsAssignableFrom
alih-alih operator kesetaraan ( ==
)?
Anda dapat menggunakan kode pendek menggunakan dinamis meskipun ini mungkin lebih lambat dari refleksi murni:
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();
Ini adalah dua metode ekstensi favorit saya yang mencakup sebagian besar kasus pemeriksaan tipe generik:
Bekerja dengan:
Memiliki kelebihan yang akan 'keluar' dari tipe generik spesifik jika itu mengembalikan true (lihat unit test untuk sampel):
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;
}
}
Inilah tes untuk menunjukkan fungsionalitas (dasar):
[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);
}
return list.GetType().IsGenericType;