web-dev-qa-db-ja.com

C#-汎用リストのアイテムタイプを取得する

汎用リストに含まれるアイテムのタイプを取得する最良の方法は何でしょうか?コレクション内の最初のアイテムを取得して.GetType()を呼び出すのは簡単ですが、コレクション内にアイテムがあるかどうかを常に確認することはできません。

それが理にかなっていることを願っています。

おかげで、
ソニー

39
Sonny Boy

Type.GetGenericArguments この目的のためのメソッド。

List<Foo> myList = ...

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

より堅牢なアプローチの場合:

_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("someList", "Type must be List<>, but was " + type.FullName);

    return type.GetGenericArguments()[0];
}
_

ただし、変数が_List<T>_と入力されている場合は、typeof(T)を使用できます。例えば:

_public static Type GetListType<T>(List<T> someList)
{
    return typeof(T);
}
_

someListパラメーターも実際には必要ないことに注意してください。このメソッドは、すでにジェネリックメソッドを使用している場合にtypeofを使用する方法の単なる例です。 Tトークンにアクセスできない場合にのみ、リフレクションアプローチを使用する必要があります(リストは、1つの型付きIListobjectなど)。

8
cdhowie
list.GetType().GetGenericArguments()[0]
6
Mehrdad

非ジェネリックコレクションでも機能する別の方法を次に示します。

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をスローします。

  • 型にインデックス演算子のオーバーロードが複数ある場合、AmbiguousMatchExceptionをスローします(例:this[string]およびthis[int])。

より洗練されたバージョンは次のとおりです。

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
Joey Adams
    public Type GetType(IEnumerable<object> resultList)
    {
        return resultList.GetType().GetElementType();
    }
2
joyce

これはどうですか、そのすべての静的(たとえば、インスタンスは必要ありません)、高速(ループなし、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());
        }

これを見るには2つの方法があることに注意してください。1つのタイプはインデクサーから返され、もう1つのタイプは列挙子から返されます。単体テストでは両方が表示されます。

楽しんでください、フランス。

追伸列挙型の場合:

    [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;
    }
2
FdW

dynamicを使用した古い質問の新しいメソッド

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

private static Type GetTypeT<T>(IEnumerable<T> data)
{
    return typeof(T);
}
1
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
0
toddmo