Как получить тип элемента массива из типа массива в .net - PullRequest
62 голосов
/ 09 ноября 2010

Скажем, у меня есть объект типа System.String[]. Я могу запросить объект типа, чтобы определить, является ли он массивом

Type t1 = typeof(System.String[]);
bool isAnArray = t1.IsArray; // should be true

Однако как я могу получить объект типа элемента массива из t1

Type t2 = ....; // should be typeof(System.String)

Ответы [ 3 ]

105 голосов
/ 09 ноября 2010

Для этой цели вы можете использовать метод экземпляра Type.GetElementType.

Type t2 = t1.GetElementType();

[Возвращает] тип объекта, охватываемого или на который ссылается текущий массив, указатель или ссылочный тип, или ноль, если текущий Тип не является массивом или указателем, или не передан по ссылке или представляет собой универсальный тип или параметр типа в определении универсального типа или универсального метода.

12 голосов
/ 24 февраля 2014

Благодаря @psaxton комментарий указывает на разницу между массивом и другими коллекциями. Как метод расширения:

public static class TypeHelperExtensions
{
    /// <summary>
    /// If the given <paramref name="type"/> is an array or some other collection
    /// comprised of 0 or more instances of a "subtype", get that type
    /// </summary>
    /// <param name="type">the source type</param>
    /// <returns></returns>
    public static Type GetEnumeratedType(this Type type)
    {
        // provided by Array
        var elType = type.GetElementType();
        if (null != elType) return elType;

        // otherwise provided by collection
        var elTypes = type.GetGenericArguments();
        if (elTypes.Length > 0) return elTypes[0];

        // otherwise is not an 'enumerated' type
        return null;
    }
}

Использование:

typeof(Foo).GetEnumeratedType(); // null
typeof(Foo[]).GetEnumeratedType(); // Foo
typeof(List<Foo>).GetEnumeratedType(); // Foo
typeof(ICollection<Foo>).GetEnumeratedType(); // Foo
typeof(IEnumerable<Foo>).GetEnumeratedType(); // Foo

// some other oddities
typeof(HashSet<Foo>).GetEnumeratedType(); // Foo
typeof(Queue<Foo>).GetEnumeratedType(); // Foo
typeof(Stack<Foo>).GetEnumeratedType(); // Foo
typeof(Dictionary<int, Foo>).GetEnumeratedType(); // int
typeof(Dictionary<Foo, int>).GetEnumeratedType(); // Foo, seems to work against key
1 голос
/ 07 мая 2017

Спасибо @ drzaus за его приятный ответ , но его можно сжать до одного лайнера (плюс проверка для типов null s и IEnumerable):

public static Type GetEnumeratedType(this Type type) =>
   type?.GetElementType()
   ?? typeof(IEnumerable).IsAssignableFrom(type)
   ? type.GenericTypeArguments.FirstOrDefault()
   : null;

Добавлены null шашки, чтобы избежать исключения, может быть, я не должен (не стесняйтесь удалять Пустые условные операторы ).Также добавлен фильтр, чтобы функция работала только с коллекциями, а не с общими типами.

И имейте в виду, что это также может быть одурачено реализованными подклассами, которые изменяют тему коллекции, и разработчик решил переместитьуниверсальный аргумент типа коллекции на более позднюю позицию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...