C# 如何从泛型类或方法的成员获取 T 的类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/557340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the type of T from a member of a generic class or method?
提问by Patrick Desjardins
Let say I have a generic member in a class or method, so:
假设我在类或方法中有一个通用成员,因此:
public class Foo<T>
{
public List<T> Bar { get; set; }
public void Baz()
{
// get type of T
}
}
When I instantiate the class, the T
becomes MyTypeObject1
, so the class has a generic list property: List<MyTypeObject1>
. The same applies to a generic method in a non-generic class:
当我实例化这个类时,它T
变成了MyTypeObject1
,所以这个类有一个通用的列表属性:List<MyTypeObject1>
。这同样适用于非泛型类中的泛型方法:
public class Foo
{
public void Bar<T>()
{
var baz = new List<T>();
// get type of T
}
}
I would like to know, what type of objects the list of my class contains. So the list property called Bar
or the local variable baz
, contains what type of T
?
我想知道,我的类列表包含什么类型的对象。那么被调用的列表属性Bar
或局部变量baz
,包含什么类型的T
?
I cannot do Bar[0].GetType()
, because the list might contain zero elements. How can I do it?
我不能做Bar[0].GetType()
,因为列表可能包含零个元素。我该怎么做?
采纳答案by Tamas Czinege
If I understand correctly, your list has the same type parameter as the container class itself. If this is the case, then:
如果我理解正确,您的列表与容器类本身具有相同的类型参数。如果是这种情况,那么:
Type typeParameterType = typeof(T);
If you are in the lucky situation of having object
as a type parameter, see Marc's answer.
如果您幸运地将其object
作为类型参数,请参阅Marc 的回答。
回答by Marc Gravell
(note: I'm assuming that all you know is object
or IList
or similar, and that the list could be any type at runtime)
(注:我假设你知道object
或IList
或类似的,并且这个名单可以是任何类型的在运行时)
If you know it is a List<T>
, then:
如果你知道它是 a List<T>
,那么:
Type type = abc.GetType().GetGenericArguments()[0];
Another option is to look at the indexer:
另一种选择是查看索引器:
Type type = abc.GetType().GetProperty("Item").PropertyType;
Using new TypeInfo:
使用新的 TypeInfo:
using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];
回答by Rauhotz
Try
尝试
list.GetType().GetGenericArguments()
回答by Ferenc Mucsi
Type:
类型:
type = list.AsEnumerable().SingleOrDefault().GetType();
回答by Ferenc Mucsi
Consider this: I use it to export 20 typed list by same way:
考虑一下:我用它以同样的方式导出 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);
}
}
回答by Thomas
The GetGenericArgument()
method has to be set on the Base Type of your instance
(whose class is a generic class myClass<T>
). Otherwise, it returns a type[0]
该GetGenericArgument()
方法必须在您的实例的基本类型上设置(其类是泛型类myClass<T>
)。否则,它返回一个类型[0]
Example:
例子:
Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();
回答by Carlos Rodriguez
That's work for me. Where myList is some unknowed kind of list.
这对我有用。其中 myList 是某种未知的列表。
IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;
回答by 3dGrabber
With the following extension method you can get away without reflection:
使用以下扩展方法,您无需反射即可逃脱:
public static Type GetListType<T>(this List<T> _)
{
return typeof(T);
}
Or more general:
或更一般的:
public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
return typeof(T);
}
Usage:
用法:
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
回答by Dan Malcolm
You can get the type of "T" from any collection type that implements IEnumerable<T> with the following:
您可以从任何实现 IEnumerable<T> 的集合类型中获取“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;
}
Note that it doesn't support collection types that implement IEnumerable<T> twice, e.g.
请注意,它不支持实现 IEnumerable<T> 两次的集合类型,例如
public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }
I suppose you could return an array of types if you needed to support this...
我想如果你需要支持这个,你可以返回一个类型数组......
Also, you might also want to cache the result per collection type if you're doing this a lot (e.g. in a loop).
此外,如果您经常这样做(例如在循环中),您可能还想缓存每个集合类型的结果。
回答by Ken Smith
I use this extension method to accomplish something similar:
我使用这个扩展方法来完成类似的事情:
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;
}
You use it like this:
你像这样使用它:
[TestMethod]
public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes()
{
typeof(Dictionary<string, Dictionary<string, object>>).GetFriendlyTypeName()
.ShouldEqual("Dictionary<String, Dictionary<String, Object>>");
}
This isn't quite what you're looking for, but it's helpful in demonstrating the techniques involved.
这不是您正在寻找的内容,但它有助于展示所涉及的技术。