假设我在类或方法中有一个泛型成员,所以:
public class Foo<T>
{
public List<T> Bar { get; set; }
public void Baz()
{
// get type of T
}
}
当我实例化类时,T
变为MyTypeObject1
,因此该类具有通用列表属性:List<MyTypeObject1>
。这同样适用于非泛型类中的泛型方法:
public class Foo
{
public void Bar<T>()
{
var baz = new List<T>();
// get type of T
}
}
我想知道,我的类列表包含什么类型的对象。因此,名为Bar
的列表属性或本地变量baz
包含哪种类型的T
?
我不能Bar[0].GetType()
,因为列表可能包含零元素。我该怎么办?
答案 0 :(得分:613)
如果我理解正确,您的列表与容器类本身具有相同的类型参数。如果是这种情况,那么:
Type typeParameterType = typeof(T);
如果您处于将object
作为类型参数的幸运情况,请参阅Marc's answer。
答案 1 :(得分:492)
(注意:我假设你所知道的只是object
或IList
或类似的,并且列表在运行时可以是任何类型)
如果你知道它是List<T>
,那么:
Type type = abc.GetType().GetGenericArguments()[0];
另一种选择是查看索引器:
Type type = abc.GetType().GetProperty("Item").PropertyType;
使用新的TypeInfo:
using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];
答案 2 :(得分:45)
使用以下扩展方法,您可以在没有反射的情况下离开:
public static Type GetListType<T>(this List<T> _)
{
return typeof(T);
}
或者更一般:
public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
return typeof(T);
}
用法:
List<string> list = new List<string> { "a", "b", "c" };
IEnumerable<string> strings = list;
IEnumerable<object> objects = list;
Type listType = list.GetListType(); // string
Type stringsType = strings.GetEnumeratedType(); // string
Type objectsType = objects.GetEnumeratedType(); // BEWARE: object
答案 3 :(得分:30)
尝试
list.GetType().GetGenericArguments()
答案 4 :(得分:13)
这对我有用。我的列表是一些未知的列表。
IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;
答案 5 :(得分:9)
考虑一下: 我用它以相同的方式导出20个类型列表:
private void Generate<T>()
{
T item = (T)Activator.CreateInstance(typeof(T));
((T)item as DemomigrItemList).Initialize();
Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
if (type == null) return;
if (type != typeof(account)) //account is listitem in List<account>
{
((T)item as DemomigrItemList).CreateCSV(type);
}
}
答案 6 :(得分:8)
您可以将此选项用作通用列表的返回类型:
public string ListType<T>(T value)
{
var valueType = value.GetType().GenericTypeArguments[0].FullName;
return valueType;
}
答案 7 :(得分:5)
必须在实例的基本类型上设置GetGenericArgument()
方法
(其类是通用类myClass<T>
)。否则,它返回一个类型[0]
示例:
Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();
答案 8 :(得分:4)
您可以从实现IEnumerable&lt; T&gt;的任何集合类型中获取“T”的类型。以下内容:
public static Type GetCollectionItemType(Type collectionType)
{
var types = collectionType.GetInterfaces()
.Where(x => x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.ToArray();
// Only support collections that implement IEnumerable<T> once.
return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}
请注意,它不支持实现IEnumerable&lt; T&gt;的集合类型。两次,例如
public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }
如果你需要支持这个,我想你可以返回一系列类型...
另外,如果您经常这样做(例如在循环中),您可能还希望缓存每个集合类型的结果。
答案 9 :(得分:4)
我使用这种扩展方法来完成类似的事情:
public static string GetFriendlyTypeName(this Type t)
{
var typeName = t.Name.StripStartingWith("`");
var genericArgs = t.GetGenericArguments();
if (genericArgs.Length > 0)
{
typeName += "<";
foreach (var genericArg in genericArgs)
{
typeName += genericArg.GetFriendlyTypeName() + ", ";
}
typeName = typeName.TrimEnd(',', ' ') + ">";
}
return typeName;
}
public static string StripStartingWith(this string s, string stripAfter)
{
if (s == null)
{
return null;
}
var indexOf = s.IndexOf(stripAfter, StringComparison.Ordinal);
if (indexOf > -1)
{
return s.Substring(0, indexOf);
}
return s;
}
你这样使用它:
[TestMethod]
public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes()
{
typeof(Dictionary<string, Dictionary<string, object>>).GetFriendlyTypeName()
.ShouldEqual("Dictionary<String, Dictionary<String, Object>>");
}
这并不是您正在寻找的,但它有助于展示所涉及的技术。
答案 10 :(得分:1)
public bool IsCollection<T>(T value){
var valueType = value.GetType();
return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype);
}
答案 11 :(得分:1)
使用3dGrabber的解决方案:
public static T GetEnumeratedType<T>(this IEnumerable<T> _)
{
return default(T);
}
//and now
var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();
答案 12 :(得分:0)
如果您想知道某个属性的基础类型,请尝试以下方法:
propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]
答案 13 :(得分:0)
我就这样做了
internal static Type GetElementType(this Type type)
{
//use type.GenericTypeArguments if exist
if (type.GenericTypeArguments.Any())
return type.GenericTypeArguments.First();
return type.GetRuntimeProperty("Item").PropertyType);
}
然后像这样称呼它
var item = Activator.CreateInstance(iListType.GetElementType());
OR
var item = Activator.CreateInstance(Bar.GetType().GetElementType());
答案 14 :(得分:-1)
对于寻求按字面意思处理类型名称的开发人员,例如使用switch语句,下面是一个示例:
public static void TypeBasedLogic<T>(T item)
{
switch (typeof(T).ToString()) //e.g. System.Int32
{
case nameof(System) + "." + nameof(Int32):
//Logic for int
Console.Write("It's an integer");
break;
case nameof(System) + "." + nameof(Double):
//Logic for double
Console.Write("It's a double");
break;
case nameof(System) + "." + nameof(Decimal):
//Logic for decimal
Console.Write("It's a decimal");
break;
case nameof(System) + "." + nameof(String):
//Logic for string
Console.Write("It's a string");
break;
default:
//logic for the rest other System or custom types
Console.Write("It's a "+ typeof(T).ToString());
break;
}
}
用法:
TypeBasedLogic(5); // outputs: It's an integer
答案 15 :(得分:-9)
类型:
type = list.AsEnumerable().SingleOrDefault().GetType();