Como posso verificar se um determinado valor é uma lista genérica?

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

Qual é a melhor maneira de verificar se o objeto fornecido é uma lista ou se pode ser convertido para uma lista?


fonte
Talvez você encontre a resposta aqui stackoverflow.com/questions/755200/…
Maksim Kondratyuk

Respostas:

96
using System.Collections;

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

}
James Couvares
fonte
4
Isso não funciona - recebo a seguinte exceção - o valor é IList. Usar o tipo genérico 'System.Collections.Generic.IList <T>' requer argumentos do tipo '1'
17
Você precisa adicionar usando System.Collections; no topo do seu arquivo de origem. A interface IList que sugeri NÃO é a versão genérica (daí a segunda verificação)
James Couvares
1
Você está certo. Isso funciona como um encanto. Eu estava testando isso em minha janela Watch e esqueci tudo sobre o namespace ausente. Gosto mais desta solução, muito simples
3
Isso não funciona. Eu acho que em 4.0 IList <T>! = IList? De qualquer forma, tive que verificar se era genérico e IEnumerable, e então verificar a existência da propriedade que eu queria verificar, "Count". Suponho que essa fraqueza seja em parte porque o WCF transforma todos os seus List <T> em T [].
1
@Edza Incorrect. Isso geralmente funciona desde List<T>e ObservableCollection<T>implementar IList.
HappyNomad
124

Para vocês que gostam de usar métodos de extensão:

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

Então, podemos fazer:

if(o.IsGenericList())
{
 //...
}
Victor Rodrigues
fonte
3
Para .Net Core, isso precisa ser ligeiramente modificado parareturn oType.GetTypeInfo().IsGenericType && oType.GetGenericTypeDefinition() == typeof(List<>);
Rob L
Funciona como um encanto! Se você tiver apenas o tipo e não o objeto, isso funcionará para você! Obrigado!!
gatsby,
Em IList<>vez disso, verificar seria mais seguro?
nl-x
15
 bool isList = o.GetType().IsGenericType 
                && o.GetType().GetGenericTypeDefinition() == typeof(IList<>));
Eoin Campbell
fonte
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
fonte
5
if(value is IList && value.GetType().GetGenericArguments().Length > 0)
{

}
BFree
fonte
Acho que você precisa de uma chamada para GetType (), por exemplo, value.GetType (). GetGenericArguments (). Comprimento> 0
ScottS
4

Com base na resposta de Victor Rodrigues, podemos conceber outro método para os genéricos. Na verdade, a solução original pode ser reduzida a apenas duas linhas:

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
fonte
3

Esta é uma implementação que funciona em .NET Standard e em interfaces:

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

E aqui estão os testes (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
fonte
1

Estou usando o seguinte código:

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

Provavelmente, a melhor maneira seria fazer algo assim:

IList list = value as IList;

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

Isso lhe dará o máximo de flexibilidade e também permitirá que você trabalhe com muitos tipos diferentes que implementam a IListinterface.

Andrew Hare
fonte
3
isso não verifica se é uma lista genérica conforme solicitado.
Lucas