Yanıtlar:
Bunun genel bir türün örneği olup olmadığını kontrol etmek istiyorsanız:
return list.GetType().IsGenericType;
Genel olup olmadığını kontrol etmek istiyorsanız List<T>
:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
Jon'un belirttiği gibi, bu tam tip denkliğini kontrol eder. Dönen false
anlamına gelmez list is List<T>
döner false
(yani amacı, bir tahsis edilemez List<T>
değişken).
Sadece türün genel olup olmadığını bilmek istemiyorum, ancak bir nesne türü bağımsız değişkenleri bilmeden belirli bir genel türün bir örneği olup olmadığını bilmek istiyorum.
Ne yazık ki çok basit değil. Genel tür bir sınıfsa (bu durumda olduğu gibi) çok kötü değil, ancak arabirimler için daha zordur. İşte bir sınıfın kodu:
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: Yorumlarda belirtildiği gibi, bu arabirimler için işe yarayabilir:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
Bu konuda bazı garip kenar vakaları olabilir sinsi bir şüphem var, ama şu anda başarısız birini bulamıyorum.
List<T>
. Arayüzler eklerseniz, bu gerçekten zor.
IsInstanceOfGenericType
bir çağrıyla değiştiremez misiniz ? IsAssignableFrom
==
Dinamik althougth kullanarak daha kısa kod kullanabilirsiniz, bu saf yansımadan daha yavaş olabilir:
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();
Bunlar, genel tip kontrolünün en uç durumlarını kapsayan iki favori uzantı yöntemimdir:
İle çalışır:
True değerini döndürürse belirli genel türü 'dışarıda bırakacak' aşırı yüke sahiptir (örnekler için birim testine bakın):
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;
}
}
İşte (temel) işlevselliği göstermek için bir test:
[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;