¿Cómo verifico si un valor dado es una lista genérica?

90
public bool IsList(object value)
    {
        Type type = value.GetType();
        // Check if type is a generic list of any type
    }

¿Cuál es la mejor manera de comprobar si el objeto dado es una lista o si se puede convertir en una lista?


fuente
Tal vez encuentre la respuesta aquí stackoverflow.com/questions/755200/…
Maksim Kondratyuk

Respuestas:

94
using System.Collections;

if(value is IList && value.GetType().IsGenericType) {

}
James Couvares
fuente
4
Esto no funciona - obtengo la siguiente excepción - el valor es IList El uso del tipo genérico 'System.Collections.Generic.IList <T>' requiere argumentos de tipo '1'
15
Necesita agregar usando System.Collections; encima de su archivo fuente. La interfaz IList que sugerí NO es la versión genérica (de ahí la segunda verificación)
James Couvares
1
Tienes razón. Esto funciona a las mil maravillas. Estaba probando esto en mi ventana Watch y me olvidé del espacio de nombres que faltaba. Me gusta más esta solución, muy simple
3
Esto no funciona. Supongo que en 4.0 IList <T>! = IList? De todos modos, tuve que verificar si era genérico e IEnumerable, y luego verificar la existencia de la propiedad que quería verificar, "Count". Supongo que esta debilidad es en parte la razón por la que WCF convierte todas sus List <T> en T [].
1
@Edza Incorrecto. Esto generalmente funciona desde List<T>y se ObservableCollection<T>implementa IList.
HappyNomad
121

Para ustedes que disfrutan del uso de métodos de extensión:

public static bool IsGenericList(this object o)
{
    var oType = o.GetType();
    return (oType.IsGenericType && (oType.GetGenericTypeDefinition() == typeof(List<>)));
}

Entonces, podríamos hacer:

if(o.IsGenericList())
{
 //...
}
Víctor Rodrigues
fuente
3
Para .Net Core, esto debe modificarse ligeramente areturn oType.GetTypeInfo().IsGenericType && oType.GetGenericTypeDefinition() == typeof(List<>);
Rob L
¡Funciona de maravilla! Si solo tiene el tipo, no el objeto, ¡esto funcionará para usted! ¡¡Gracias!!
gatsby
¿ IList<>Sería más seguro buscar en su lugar?
nl-x
14
 bool isList = o.GetType().IsGenericType 
                && o.GetType().GetGenericTypeDefinition() == typeof(IList<>));
Eoin Campbell
fuente
6
public bool IsList(object value) {
    return value is IList 
        || IsGenericList(value);
}

public bool IsGenericList(object value) {
    var type = value.GetType();
    return type.IsGenericType
        && typeof(List<>) == type.GetGenericTypeDefinition();
}
Atif Aziz
fuente
5
if(value is IList && value.GetType().GetGenericArguments().Length > 0)
{

}
BFree
fuente
Creo que necesita una llamada a GetType (), por ejemplo, value.GetType (). GetGenericArguments (). Length> 0
ScottS
4

Según la respuesta de Victor Rodrigues, podemos idear otro método para los genéricos. De hecho, la solución original se puede reducir a solo dos líneas:

public static bool IsGenericList(this object Value)
{
    var t = Value.GetType();
    return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>);
}

public static bool IsGenericList<T>(this object Value)
{
    var t = Value.GetType();
    return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<T>);
}
James M
fuente
3

Aquí hay una implementación que funciona en .NET Standard y funciona con interfaces:

    public static bool ImplementsGenericInterface(this Type type, Type interfaceType)
    {
        return type
            .GetTypeInfo()
            .ImplementedInterfaces
            .Any(x => x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == interfaceType);
    }

Y aquí están las pruebas (xunit):

    [Fact]
    public void ImplementsGenericInterface_List_IsValidInterfaceTypes()
    {
        var list = new List<string>();
        Assert.True(list.GetType().ImplementsGenericInterface(typeof(IList<>)));
        Assert.True(list.GetType().ImplementsGenericInterface(typeof(IEnumerable<>)));
        Assert.True(list.GetType().ImplementsGenericInterface(typeof(IReadOnlyList<>)));
    }

    [Fact]
    public void ImplementsGenericInterface_List_IsNotInvalidInterfaceTypes()
    {
        var list = new List<string>();
        Assert.False(list.GetType().ImplementsGenericInterface(typeof(string)));
        Assert.False(list.GetType().ImplementsGenericInterface(typeof(IDictionary<,>)));
        Assert.False(list.GetType().ImplementsGenericInterface(typeof(IComparable<>)));
        Assert.False(list.GetType().ImplementsGenericInterface(typeof(DateTime)));
    }
Jeff Siemens
fuente
1

Estoy usando el siguiente código:

public bool IsList(Type type) => IsGeneric(type) && (
            (type.GetGenericTypeDefinition() == typeof(List<>))
            || (type.GetGenericTypeDefinition() == typeof(IList<>))
            );
Yashar Aliabbasi
fuente
0

Probablemente, la mejor manera sería hacer algo como esto:

IList list = value as IList;

if (list != null)
{
    // use list in here
}

Esto le dará la máxima flexibilidad y también le permitirá trabajar con muchos tipos diferentes que implementan la IListinterfaz.

Andrew Hare
fuente
3
esto no comprueba si es una lista genérica como se pidió.
Lucas