user1017882
user1017882

Reputation:

Passing a lambda expression as parameter to a method?

It seems like it'd be a common requirement, but I cannot find a solution to this anywhere.

I have a method which will OrderBy a collection depending on a parameter passed to it.

I'd like to pass the contents of an 'OrderBy' to the method, but cannot work out how to do it.

What I've Tried

I've tried a switch with a string (i.e. if you pass 'Name' it'll hit the case which orders it by name), but this feels 'hacky' and unnecessary.

I know it's something like Func<TEntity, TResult>, but I can't quite crack it.

PSEUDO CODE:

GetOrderedCollection([NOT SURE] orderBy)
{
  return collection.OrderBy(orderBy);
}

Upvotes: 3

Views: 8666

Answers (5)

ryanyuyu
ryanyuyu

Reputation: 6486

Yes you are looking for a Func<TEntity, TResult> orderingFunc. The important thing is that the output (the TResult) is an IComparable so that the OrderBy function can properly sort your results.

So something like this will work fine:

public void OrderByDynamic(Func<Model, object> orderByFunc)
{
    collection = collection.OrderBy(orderByFunc); //don't forget to assign the return value
}

You could call this with lambda functions like normal:

OrderByDynamic(m => m.SortObj); //as long as this property/return value is IComparable

A .NET Fiddle demonstrating this idea

Upvotes: 0

BgrWorker
BgrWorker

Reputation: 679

OrderBy is an extension method with the following signature:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector
)

(source: https://msdn.microsoft.com/it-it/library/bb534966%28v=vs.110%29.aspx )

so your method needs a Func as its argument, where TSource is the List type, and TKey is the type returned by your lambda. An example would be:

public void Method<TSource, TKey>(List<TSource> list, Func<TSource, TKey> func)
        {
            ...
            IOrderedEnumerable<TSource> orderedEnumerable = list.OrderBy(func);
        }

EDIT: I also noticed that in your example code you declared your method as void, bu then you're trying to return an IOrderedEnumerable. If you want to get the ordered collection back, your method needs to have at least an IEnumerable type (but that would defeat the purpose of ordering it, as IEnumerables do not guarantee order. A more likely implementation would be to return a List<TSource> and call list.OrderBy(func).ToList()

Upvotes: 3

David Arno
David Arno

Reputation: 43254

In it's most generic form, your method would need to look like:

IOrderedEnumerable<T1> GetOrderedCollection<T1, T2>(IEnumerable<T1> collection, Func<T1, T2> orderBy)
{
    return collection.OrderBy(orderBy);
}

T1 being the type of the items in the list and T2 being the type of the property of T1 that you want to order on.

Upvotes: 1

Melvin
Melvin

Reputation: 324

The parameter has to be either a Func or an Action. See the answer to this question for more information.

Upvotes: -1

Glorfindel
Glorfindel

Reputation: 22641

Does this satisfy your requirements?

    static void Main(string[] args) {           
        var objects = new List<Test>();
        GetOrderedCollection(objects, x => x.Name);
    }

    class Test {
        public string Name { get; set; }
    }

    static IEnumerable<TEntity> GetOrderedCollection<TEntity>(IEnumerable<TEntity> objects, Func<TEntity, object> orderBy) {
        return objects.OrderBy(orderBy);
    }

Upvotes: 0

Related Questions