Pregunta ¿Cómo obtener el tipo de T de un miembro de una clase o método genérico?


Digamos que tengo un miembro genérico en una clase o método, así que:

public class Foo<T>
{
    public List<T> Bar { get; set; }

    public void Baz()
    {
        // get type of T
    }   
}

Cuando instanciar la clase, el T se convierte MyTypeObject1, entonces la clase tiene una propiedad de lista genérica: List<MyTypeObject1>. Lo mismo se aplica a un método genérico en una clase no genérica:

public class Foo
{
    public void Bar<T>()
    {
        var baz = new List<T>();

        // get type of T
    }
}

Me gustaría saber qué tipo de objetos contiene la lista de mi clase. Entonces la propiedad de la lista llamada Bar o la variable local baz, contiene qué tipo de T?

No puedo hacerlo Bar[0].GetType(), porque la lista puede contener cero elementos. ¿Cómo puedo hacerlo?


549
2018-02-17 15:24


origen


Respuestas:


Si entiendo correctamente, su lista tiene el mismo parámetro de tipo que la clase contenedor. Si este es el caso, entonces:

Type typeParameterType = typeof(T);

Si estás en la afortunada situación de tener object como parámetro de tipo, ver La respuesta de Marc.


554
2018-02-17 15:27



(nota: asumo que todo lo que sabes es object o IList o similar, y que la lista podría ser de cualquier tipo en tiempo de ejecución)

Si sabes que es un List<T>, entonces:

Type type = abc.GetType().GetGenericArguments()[0];

Otra opción es mirar el indexador:

Type type = abc.GetType().GetProperty("Item").PropertyType;

Usando nuevo TypeInfo:

using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];

461
2018-02-17 15:26



Con el siguiente método de extensión puede escapar sin reflexionar:

public static Type GetListType<T>(this List<T> _)
{
    return typeof(T);
}

O más general:

public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return typeof(T);
}

Uso:

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

41
2017-09-23 10:05



Tratar

list.GetType().GetGenericArguments()

26
2018-02-17 15:26



Eso es trabajo para mí. Donde myList es un tipo de lista desconocida.

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;

12
2018-05-18 10:01



Considera esto: Lo uso para exportar 20 tipos de lista de la misma manera:

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

9
2018-03-29 19:36



Si no necesita toda la variable Tipo y solo desea verificar el tipo, puede crear fácilmente una variable de temperatura y usar es el operador.

T checkType = default(T);

if (checkType is MyClass)
{}

6
2018-05-08 10:21



los GetGenericArgument() El método debe establecerse en el tipo base de su instancia (cuya clase es una clase genérica myClass<T>) De lo contrario, devuelve un tipo [0]

Ejemplo:

Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();

5
2017-07-29 14:26



public string ListType<T>(T value){
    var valueType = value.GetType().GenericTypeArguments[0].FullName;
    return value;
}

 Puede usar este para volver a ejecutar el tipo de lista genérica. 


4
2018-01-05 11:45



Puede obtener el tipo de "T" de cualquier tipo de colección que implemente IEnumerable <T> con lo siguiente:

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

Tenga en cuenta que no admite tipos de colecciones que implementen IEnumerable <T> dos veces, p. Ej.

public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }

Supongo que podría devolver una variedad de tipos si necesitara apoyar esto ...

Además, es posible que desee almacenar en caché el resultado por tipo de colección si lo hace mucho (por ejemplo, en un bucle).


3
2018-04-16 15:31