Метод расширения для универсальных типов List <> - PullRequest
0 голосов
/ 01 мая 2018

TL; DL: упрощение method<returnType, ListType>(this List<ListType>, ...) до method<returnType>(this List<anyType>, ...) для общих списков

Я хочу написать метод расширения, который позволит мне получить значения всех свойств "P" в Списке (любого типа объекта)

Пока я получил этот метод для работы:

public static T[] selectAll<T, U>(this List<U> list, string property)
{
    List<T> r = new List<T>();          // prepare a list of values of the desired type to be returned
    foreach(object o in list)
    {
        Type mt = o.GetType();          // what are we actually dealing with here? (List of what?)   <-- This should be the same as Type U
        IList<PropertyInfo> props = new List<PropertyInfo>(mt.GetProperties());          // Get all properties within that type
        foreach(PropertyInfo p in props)
        {
            if (p.Name == property)                   // Are we looking for this property?
                r.Add((T)p.GetValue(o, null));        // then add it to the list to be returned
        }
    }
    return r.ToArray();
}

Поскольку вы не можете просто иметь неизвестный тип возвращаемого значения, я понимаю, что необходимо указать тип возвращаемого значения в вызове метода, например:

List<Control> SomeListOfControls = ...

string[] s = SomeListOfControls.selectAll< строка , Control>("Text");

Но, поскольку тип элементов в этом списке довольно не имеет значения для этого метода, я хочу исключить переменную типа из уравнения. Я хотел бы просто позвонить

List<Control> SomeListOfControls = ...

string[] s = SomeListOfControls.selectAll<string>("Text"); <- Вы чертовски хорошо знаете, из чего состоит этот Список>. <</p>

например.

Но я не могу придумать, как это сделать. Еще до компиляции я вижу, что

public static T[] selectAll<T>(this List<> list, string property)

- это Unexpected use of an unbound generic name (что означает List<>).

И List<object> не регистрируется как расширение для всех видов List<?extends object>, так сказать.

Как, если это вообще возможно, я могу заставить это работать?

PS: Кажется, что может существовать "нативный" способ (.net или даже C # в целом) для получения коллекции P из коллекции, которая может иметь свойства типа P T - Я не мог понять это, используя select и все ... Но если есть: я был бы рад узнать об этом:)

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Последствия (что пошло не так, где)

Хотя я импортировал (using) оба

System.Collections.Generic

и

System.Collections.Specialized

Я не знал, что классы, от которых эти пространства имен частично наследуются, фактически находятся в System.Collections. Я думал, что получаю обе половинки пирога, тогда как я получаю две начинки, пропуская корочку.

Поэтому, когда бы я ни пытался использовать IEnumerable, например, моя дорогая и надежная IDE (Visual Studio 2017) не принимала его без индикатора типа.

Для тех, кто приходит сюда через Google с такой же проблемой:

Использование .Generic и .Specialized не покроет вас , большая часть того, из чего извлекаются типы коллекций, находится в родительском System.Collections.

public static T[] selectAll<T>(this IList list, string property){
    ...
}

и

public static T[] selectAll<T>(this IEnnumerable list, string property){
    ...
}

может служить вам правильно.

Хотя для моего случая, как описано выше,

public static T[] selectAll<T>(this IEnumerable<object> list, string property){
    ...
}

Работал так же хорошо (тогда как IList<object> не удалось зарегистрировать как расширение List<? >

Названия пространств и понятий могут вводить в заблуждение:

Я бы посчитал IList<Type> специализированным (по типу) и IList универсальным (поскольку он применим ко всем <Type> с) - но в мире C # это наоборот: сам по себе IList считается "неуниверсальным" - к вопросу об универсальности ... к вопросу обращаются извне (как это трактуется в контексте), а не изнутри (что он (или может) содержать) - что-то программист высокого уровня как я, может интуитивно ошибиться.

В итоге:

  • System.Collections состоит из более чем суммы его классов

  • Интуитивно Обобщенные коллекции называются неуниверсальными, потому что полномочия более низкого уровня, о которых говорится, так:

  • System.Collections.IEnumerable, кажется, применяется ко всем видам списков

  • Чтение официальных документов, как правило, полезно. (Подождите ... вообще или конкретно? О, кто знает больше: P)

0 голосов
/ 01 мая 2018

Похоже, вы ищете неуниверсальную версию для параметра - либо IList, либо IEnumerable будет работать

public static T[] selectAll<T>(this IList list, string property){
    ...
}
...