Antworten:
Wenn Sie überprüfen möchten, ob es sich um eine Instanz eines generischen Typs handelt:
return list.GetType().IsGenericType;
Wenn Sie überprüfen möchten, ob es sich um ein Generikum handelt List<T>
:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
Wie Jon betont, überprüft dies die genaue Typäquivalenz. Rückgabe false
bedeutet nicht unbedingt list is List<T>
Rückgabe false
(dh das Objekt kann keiner List<T>
Variablen zugewiesen werden).
Ich gehe davon aus, dass Sie nicht nur wissen möchten, ob der Typ generisch ist, sondern ob ein Objekt eine Instanz eines bestimmten generischen Typs ist, ohne die Typargumente zu kennen.
Es ist leider nicht besonders einfach. Es ist nicht schlecht, wenn der generische Typ eine Klasse ist (wie in diesem Fall), aber es ist schwieriger für Schnittstellen. Hier ist der Code für eine Klasse:
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>
{
}
}
BEARBEITEN: Wie in den Kommentaren angegeben, funktioniert dies möglicherweise für Schnittstellen:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
Ich habe den Verdacht, dass es einige unangenehme Randfälle gibt, aber ich kann keinen finden, für den es momentan fehlschlägt.
List<T>
in irgendeiner Form getroffen haben . Wenn Sie Schnittstellen einschließen, ist das wirklich schwierig.
IsInstanceOfGenericType
durch einen Aufruf von IsAssignableFrom
anstelle des Gleichheitsoperators ( ==
) ersetzen ?
Sie können kürzeren Code mit dynamischer Verwendung verwenden, obwohl dies langsamer sein kann als reine Reflexion:
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();
Dies sind meine beiden bevorzugten Erweiterungsmethoden, die die meisten Randfälle der generischen Typprüfung abdecken:
Arbeitet mit:
Hat eine Überladung, die den spezifischen generischen Typ "out" macht, wenn er true zurückgibt (siehe Unit-Test für Beispiele):
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;
}
}
Hier ist ein Test, um die (grundlegende) Funktionalität zu demonstrieren:
[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;