C# - 获取通用列表的项目类型

Posted

技术标签:

【中文标题】C# - 获取通用列表的项目类型【英文标题】:C# - Get the item type for a generic list 【发布时间】:2011-05-26 01:16:57 【问题描述】:

获取通用列表包含的项目类型的最佳方法是什么?获取集合中的第一个项目并调用 .GetType() 很容易,但我不能总是确定集合中是否会有项目。

希望这是有道理的。

谢谢, 桑尼

【问题讨论】:

您对类型了解多少?你能提供一个示例上下文吗? 【参考方案1】:

您可以为此目的使用Type.GetGenericArguments 方法。

List<Foo> myList = ...

Type myListElementType = myList.GetType().GetGenericArguments().Single();

【讨论】:

如果T 令牌在范围内(例如,在接受List&lt;T&gt; 的方法中),您也可以使用typeof(T)。如果List&lt;T&gt; 存储在object 类型的变量中,则必须使用上述方法。 你今天早些时候没有回答另一个问题吗,几乎完全一样? @LukeH:是的,闪电确实击中了两次 :) ***.com/questions/4448871/… @Lambert:我不是降价专家,但我选择了一个块并单击“代码示例”图标。我建议你点击橙色的“?”在答案框的右上角获取有关此内容如何工作的更多信息。【参考方案2】:

对于更稳健的方法:

public static Type GetListType(object someList)

    if (someList == null)
        throw new ArgumentNullException("someList");

    var type = someList.GetType();

    if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(List<>))
        throw new ArgumentException("Type must be List<>, but was " + type.FullName, "someList");

    return type.GetGenericArguments()[0];

但是如果你的变量是List&lt;T&gt;,那么你可以直接使用typeof(T)。例如:

public static Type GetListType<T>(List<T> someList)

    return typeof(T);

请注意,您甚至不需要someList 参数。如果您已经在通用方法中,此方法只是您如何使用typeof 的示例。仅当您无权访问T 标记时才需要使用反射方法(列表存储在非泛型类型变量中,例如类型为IListobject 等) .

【讨论】:

天啊,很好的错误处理。您可能还想添加可本地化的错误文本。 ;) 不错。一个小问题 - 传递给 new ArgumentException 的参数是错误的。【参考方案3】:
list.GetType().GetGenericArguments()[0]

【讨论】:

谢谢!!这真的很有帮助!【参考方案4】:

这是另一种适用于非泛型集合的方法:

static Type GetItemType(Type collectionType)

    return collectionType.GetMethod("get_Item").ReturnType;

即获取foo[x]的返回类型,其中foo为指定类型。

例子:

// Generic type; prints System.Int32
Console.WriteLine(GetItemType(typeof(List<int>)));

// Non-generic type; prints System.String
Console.WriteLine(GetItemType(typeof(System.Collections.Specialized.StringCollection)));

不过,上面的 GetItemType 方法有几个问题:

如果类型没有索引运算符,它会抛出 NullReferenceException

如果该类型对索引运算符有多个重载(例如 this[string]this[int]),则会抛出 AmbiguousMatchException

这是一个更精致的版本:

public static Type GetItemType(this Type collectionType)

    var types =
        (from method in collectionType.GetMethods()
         where method.Name == "get_Item"
         select method.ReturnType
        ).Distinct().ToArray();
    if (types.Length == 0)
        return null;
    if (types.Length != 1)
        throw new Exception(string.Format("0 has multiple item types", collectionType.FullName));
    return types[0];

【讨论】:

【参考方案5】:

这个怎么样,它都是静态的(例如,不需要实例),并且快速(没有循环,不使用 linq),而且很简单 :) 这些适用于集合:

    [System.Diagnostics.DebuggerHidden]
    public static Type GetIndexedType(this ICollection poICollection)
    
        PropertyInfo oPropertyInfo = poICollection == null ? null : poICollection.GetType().GetProperty("Item");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    

    [System.Diagnostics.DebuggerHidden]
    public static Type GetEnumeratedType(this ICollection poICollection)
    
        PropertyInfo oPropertyInfo = poICollection == null ? null : poICollection.GetType().GetMethod("GetEnumerator").ReturnType.GetProperty("Current");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    

还有一些简单的单元测试:

        [Test]
        public void GetIndexedType()
        
            Assert.AreEqual(null, ((ICollection)null).GetIndexedType());
            Assert.AreEqual(typeof(int), (new List<int>()).GetIndexedType());
            Assert.AreEqual(typeof(bool), (new SortedList<string, bool>()).GetIndexedType());
        

        [Test]
        public void GetEnumeratedType()
        
            Assert.AreEqual(null, ((ICollection)null).GetEnumeratedType());
            Assert.AreEqual(typeof(int), (new List<int>()).GetEnumeratedType());
            Assert.AreEqual(typeof(KeyValuePair<string, bool>), (new SortedList<string, bool>()).GetEnumeratedType());
        

请注意,有两种方法可以查看这一点,一种类型可能由索引器返回,另一种类型可能由枚举器返回。单元测试确实显示了两者。

玩得开心, 弗兰斯。

附:对于可枚举:

    [System.Diagnostics.DebuggerHidden]
    public static Type GetEnumeratedType(this System.Collections.IEnumerable poIEnumerable)
    
        PropertyInfo oPropertyInfo = poIEnumerable == null ? null : poIEnumerable.GetType().GetMethod("GetEnumerator").ReturnType.GetProperty("Current");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    

对于枚举器:

    [System.Diagnostics.DebuggerHidden]
    public static Type GetEnumeratedType(this System.Collections.IEnumerator poIEnumerator)
    
        PropertyInfo oPropertyInfo = poIEnumerator == null ? null : poIEnumerator.GetType().GetProperty("Current");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    

【讨论】:

这里你的方法接受每个接口的非泛型版本,但只有当它们实际上实现了泛型版本时才会按预期工作。如果你有这些要求,你也可以让方法直接接受接口的通用版本。【参考方案6】:
    public Type GetType(IEnumerable<object> resultList)
    
        return resultList.GetType().GetElementType();
    

【讨论】:

虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性 cmets 挤满你的代码,因为这会降低代码和解释的可读性!【参考方案7】:

dynamic的老问题新方法

void Foo()
   Type type GetTypeT(data as dynamic);


private static Type GetTypeT<T>(IEnumerable<T> data)

    return typeof(T);

【讨论】:

【参考方案8】:
Public Shared Function ListItemType(ListType As System.Type) As System.Type

  If Not ListType.IsGenericType Then
    If ListType.BaseType IsNot Nothing AndAlso ListType.BaseType.IsGenericType Then
      Return ListItemType(ListType.BaseType)
    End If
  Else
    Return ListType.GetGenericArguments.Single
  End If
End Function

【讨论】:

【参考方案9】:

这是一个也适用于派生类的解决方案。

因为有了这个类:

  public class SubList : List<int>
     

如果您致电:subList.GetType().GetGenericArguments().Single()

它会抛出一个System.InvalidOperationException

使用这种方法,它适用于派生类:

public Type GetListItemType<T>(List<T> list)

  Type type = list.GetType();
  while (type != typeof(List<T>))
    type = type.BaseType;
  return type.GetGenericArguments().Single();



var list = new List<int>();
var subList = new SubList();
Console.WriteLine(GetListItemType(list)); // System.Int32
Console.WriteLine(GetListItemType(subList)); // System.Int32

【讨论】:

以上是关于C# - 获取通用列表的项目类型的主要内容,如果未能解决你的问题,请参考以下文章

C#从反射类型实例化通用列表[重复]

C#:在运行时获取类型参数以传递给通用方法[重复]

C#泛型列表<T>如何获取T的类型? [复制]

TypeScript:相当于 C# 的用于扩展类的通用类型约束?

C#在安装应用程序之前和之后获取文件类型

C#如何通过类名获取类,并进行相应的操作?