汎用リストに含まれるアイテムのタイプを取得する最良の方法は何でしょうか?コレクション内の最初のアイテムを取得して.GetType()を呼び出すのは簡単ですが、コレクション内にアイテムがあるかどうかを常に確認することはできません。
それが理にかなっていることを願っています。
おかげで、
ソニー
Type.GetGenericArguments
この目的のためのメソッド。
List<Foo> myList = ...
Type myListElementType = myList.GetType().GetGenericArguments().Single();
より堅牢なアプローチの場合:
_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つの型付きIList
、object
など)。
list.GetType().GetGenericArguments()[0]
非ジェネリックコレクションでも機能する別の方法を次に示します。
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];
}
public Type GetType(IEnumerable<object> resultList)
{
return resultList.GetType().GetElementType();
}
これはどうですか、そのすべての静的(たとえば、インスタンスは必要ありません)、高速(ループなし、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;
}
dynamic
を使用した古い質問の新しいメソッド
void Foo(){
Type type GetTypeT(data as dynamic);
}
private static Type GetTypeT<T>(IEnumerable<T> data)
{
return typeof(T);
}
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