Search code examples
c#.netextension-methods

Extend method for generic List<> types


TL;DL: simplify method<returnType, ListType>(this List<ListType>, ...) to method<returnType>(this List<anyType>, ...) for generic Lists

I'm looking to write an extension method that allows me to get the values of all properties "P" within a List of (any type of object)

So far, I got this method to work:

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();
}

Because you can't simply have an unknown return type, I understand that it's necessary to indicate the return type in the method call, e.g:

List<Control> SomeListOfControls = ...

string[] s = SomeListOfControls.selectAll<string, Control>("Text");

But, since the Type of the items within that list is rather irrelevant for this method, I want to eliminate the Type variable from the equation. I wish I could simply call

List<Control> SomeListOfControls = ...

string[] s = SomeListOfControls.selectAll<string>("Text"); <-- You know damn well what this List consists of >.<

for example.

But I can't think of a way to do this. Even before compiling I can see that

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

is an Unexpected use of an unbound generic name (meaning List<>).

And List<object> fails to register as an extension for all kinds of List<?extends object>, so to speak.

How, if at all possible, can I make this work?

PS: It seems like there might be a "native" way (.net or even C# in general) to retrieve a collection of <T> P from a collection that may have properties P of type T - I couldn't figure it out using select and all... But if there is: I'd be happy to learn about it :)


Solution

  • Looks like you are looking for non-generic version for parameter - either IList or IEnumerable would work

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