Jak sprawdzić, czy podana wartość jest listą ogólną?

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

Jaki jest najlepszy sposób sprawdzenia, czy dany obiekt jest listą, czy może być rzutowany na listę?


źródło
Może tutaj znajdziesz odpowiedź stackoverflow.com/questions/755200/…
Maksim Kondratyuk

Odpowiedzi:

94
using System.Collections;

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

}
James Couvares
źródło
4
To nie działa - pojawia się następujący wyjątek - wartość to IList Używanie typu ogólnego „System.Collections.Generic.IList <T>” wymaga argumentów typu „1”
15
Musisz dodać za pomocą System.Collections; na górze pliku źródłowego. Interfejs IList, który zasugerowałem, NIE jest wersją ogólną (stąd druga kontrola)
James Couvares
1
Masz rację. To działa jak urok. Testowałem to w moim oknie Watch i zapomniałem o brakującej przestrzeni nazw. To rozwiązanie podoba mi się bardziej, bardzo proste
3
To nie działa. Myślę, że w 4.0 IList <T>! = IList? W każdym razie musiałem sprawdzić, czy jest to rodzajowe i IEnumerable, a następnie sprawdzić, czy istnieje właściwość, którą chciałem sprawdzić, „Count”. Przypuszczam, że ta słabość jest częściowo powodem, dla którego WCF zamienia wszystkie twoje List <T> w T [].
1
@Edza Niepoprawne. To zazwyczaj działa od List<T>i ObservableCollection<T>wdrożyć IList.
HappyNomad
121

Dla was, którzy lubią korzystać z metod rozszerzających:

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

Mogliśmy więc zrobić:

if(o.IsGenericList())
{
 //...
}
Victor Rodrigues
źródło
3
W przypadku .Net Core należy to nieznacznie zmodyfikować nareturn oType.GetTypeInfo().IsGenericType && oType.GetGenericTypeDefinition() == typeof(List<>);
Rob L
Działa jak marzenie! Jeśli masz tylko typ, a nie obiekt, to zadziała! Dzięki!!
gatsby,
Czy sprawdzanie IList<>zamiast tego byłoby bezpieczniejsze?
nl-x
14
 bool isList = o.GetType().IsGenericType 
                && o.GetType().GetGenericTypeDefinition() == typeof(IList<>));
Eoin Campbell
źródło
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
źródło
5
if(value is IList && value.GetType().GetGenericArguments().Length > 0)
{

}
BFree
źródło
Myślę, że potrzebujesz wywołania GetType () np. Value.GetType (). GetGenericArguments (). Length> 0
ScottS
4

Opierając się na odpowiedzi Victora Rodriguesa, możemy opracować inną metodę dla leków generycznych. W rzeczywistości oryginalne rozwiązanie można sprowadzić tylko do dwóch wierszy:

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.
źródło
3

Oto implementacja, która działa w standardzie .NET Standard i działa na interfejsach:

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

A oto testy (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
źródło
1

Używam następującego kodu:

public bool IsList(Type type) => IsGeneric(type) && (
            (type.GetGenericTypeDefinition() == typeof(List<>))
            || (type.GetGenericTypeDefinition() == typeof(IList<>))
            );
Yashar Aliabbasi
źródło
0

Prawdopodobnie najlepszym sposobem byłoby zrobienie czegoś takiego:

IList list = value as IList;

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

Zapewni to maksymalną elastyczność, a także umożliwi pracę z wieloma różnymi typami, które implementują IListinterfejs.

Andrew Hare
źródło
3
to nie sprawdza, czy jest to lista ogólna, o którą pytano.
Lucas