假设我在类或方法中有一个泛型成员,如下所示:

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(),因为列表可能包含零元素。我该怎么做?


当前回答

(注意:我假设您所知道的都是对象或IList或类似的,并且列表可以是运行时的任何类型)

如果您知道它是一个列表<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];

其他回答

考虑一下:

我使用它以相同的方式导出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);
    }
}

我是这样做的:

internal static Type GetElementType(this Type type)
{
    // Use type.GenericTypeArguments if it exists
    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());

类型:

type = list.AsEnumerable().SingleOrDefault().GetType();

如果我理解正确,您的列表具有与容器类本身相同的类型参数。如果是这种情况,那么:

Type typeParameterType = typeof(T);

如果您幸运地将对象作为类型参数,请参阅Marc的答案。

我使用这个扩展方法来完成类似的任务:

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>>");
}

这不是你想要的,但它有助于演示所涉及的技术。