Как мне проверить, является ли данное значение общим списком?

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

Как лучше всего проверить, является ли данный объект списком или его можно преобразовать в список?


источник
Возможно, вы найдете здесь ответ stackoverflow.com/questions/755200/…
Максим Кондратюк

Ответы:

94
using System.Collections;

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

}
Джеймс Куварес
источник
4
Это не работает - я получаю следующее исключение - значение - IList. Использование универсального типа «System.Collections.Generic.IList <T>» требует аргументов типа «1»
15
Вам нужно добавить using System.Collections; поверх исходного файла. Предлагаемый мной интерфейс IList НЕ является универсальной версией (отсюда и вторая проверка)
Джеймс Куварес,
1
Ты прав. Это работает как шарм. Я тестировал это в своем окне Watch и совершенно забыл об отсутствующем пространстве имен. Мне больше нравится это решение, очень простое
3
Это не работает. Я бы предположил, что в 4.0 IList <T>! = IList? В любом случае, мне пришлось проверить, является ли он общим и IEnumerable, а затем проверить наличие свойства «Count», которое я хотел проверить. Я полагаю, что эта слабость отчасти объясняется тем, что WCF превращает все ваши List <T> в T [].
1
@Edza Неверно. Это , как правило , работает с List<T>и ObservableCollection<T>реализации IList.
HappyNomad
121

Для вас, ребята, которым нравится использовать методы расширения:

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

Итак, мы могли:

if(o.IsGenericList())
{
 //...
}
Виктор Родригес
источник
3
Для .Net Core это нужно немного изменить доreturn oType.GetTypeInfo().IsGenericType && oType.GetGenericTypeDefinition() == typeof(List<>);
Роб Л.
Работает как шарм! Если у вас есть только тип, а не объект, это сработает для вас! Благодарность!!
Гэтсби 05
Будет ли проверка IList<>вместо этого безопаснее?
nl-x
14
 bool isList = o.GetType().IsGenericType 
                && o.GetType().GetGenericTypeDefinition() == typeof(IList<>));
Эоин Кэмпбелл
источник
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();
}
Атиф Азиз
источник
5
if(value is IList && value.GetType().GetGenericArguments().Length > 0)
{

}
BFree
источник
Я думаю, вам нужен вызов GetType (), например value.GetType (). GetGenericArguments (). Length> 0
ScottS
4

Основываясь на ответе Виктора Родригеса, мы можем разработать другой метод для дженериков. Фактически исходное решение можно свести всего к двум строчкам:

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>);
}
Джеймс М
источник
3

Вот реализация, которая работает в .NET Standard и работает с интерфейсами:

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

А вот и тесты (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)));
    }
Джефф Сименс
источник
1

Я использую следующий код:

public bool IsList(Type type) => IsGeneric(type) && (
            (type.GetGenericTypeDefinition() == typeof(List<>))
            || (type.GetGenericTypeDefinition() == typeof(IList<>))
            );
Яшар Алиаббаси
источник
0

Наверное, лучше всего было бы сделать что-то вроде этого:

IList list = value as IList;

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

Это даст вам максимальную гибкость, а также позволит вам работать со многими различными типами, реализующими IListинтерфейс.

Эндрю Хэйр
источник
3
это не проверяет, является ли это общим списком, как просили.
Лукас,