3

How can I define a lambdaexpression that I want to use in a linq query as a variable?

For example when sorting a generic list by different properties of the listitems:

 IList<SampleClass> list = new List<SampleClass>();

 // Populate list
 ...

 list.OrderBy(sampleclass => sampleclass.property1);
 list.OrderBy(sampleclass => sampleclass.property2);

I would like to define the lambda expression (sampleclass => sampleclass.property1) in a variable and call:

// ??? define expression in a variable ???
Expression expression = sampleclass => sampleclass.property1;

// Sort list by variable expression
list.OrderBy(expression);

Thanks in advance Tobi

Tobias
  • 2,945
  • 5
  • 41
  • 59

6 Answers6

5

You can use one of Func overloads (Func<T, TResult> precisely):

Func<SampleClass, PropertyType> expr = sampleclass => sampleclass.property1;
list.OrderBy(expr);

PropertyType is the type of variable stored as property1 in your SampleClass. If it was for example string, you would use Func<SampleClass, string>.

k.m
  • 30,794
  • 10
  • 62
  • 86
2

Define a Func<TSampleClass, TPropertyType> as follows:

  List<SampleClass> list = new List<SampleClass>();   
  Func<SampleClass, int> expr = (c) => c.SomeProperty;
  _HungerLevel = level;


  class SampleClass
  {
    public int SomeProperty { get; set; }
  }
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
1

You can use:

Func<SampleClass, int> f = sampleClass => sampleClass.Property1;
list.OrderBy(f);

This presumes the type of Property1 is int.

aligray
  • 2,812
  • 4
  • 26
  • 35
1

You have almost already done it.

The parameter is any function taking an item from the sequence and giving its key as a result (the key on which the ordering will be done). A lambda expression is just a variety of such a function.

These notations are possible :

list.OrderBy(sampleclass => sampleclass.property1);

or

Func<SampleClass,string> getKey = sampleclass => sampleclass.property1;
list.OrderBy(getKey);

or

string GetKey(SampleClass sampleclass)
{
    return sampleclass.property1;
}

list.OrderBy(GetKey);

(I supposed here that property1 was a string but it's of course not a requirement !)

Ssithra
  • 710
  • 3
  • 8
0

Just like other people said, you can use Func<T, TResult> to store delegate to your function.

If you want to use something else than Linq-To-Objects, then you should enclose this in Expression too. Something like Expression<Func<T, TResult>>.

Euphoric
  • 12,645
  • 1
  • 30
  • 44
0

If you are talking purely about LINQ to Objects, there's no need for Expressions here because the argument to Enumerable.OrderBy is a Func delegate:

var list = new List<SampleClass> ();

Func<SampleClass, PropertyType1) orderSelector1 = (obj => obj.Property1); // parentheses for clarity
var sequence1 = list.OrderBy (orderSelector1);

Func<SampleClass, PropertyType2) orderSelector1 = (obj => obj.Property2);
var sequence2 = list.OrderBy (orderSelector2);

If you want to assign multiple times, you can make Func return object:

var list = new List<SampleClass> ();
Func<SampleClass, object> orderSelector;

orderSelector = (obj => obj.Property1);
var sequence1 = list.OrderBy (orderSelector);

orderSelector = (obj => obj.Property2);
var sequence2 = list.OrderBy (orderSelector);

If you truly want dynamic property selection, i.e. calling OrderBy with a property specified by a string, you would need Expressions. There are plenty of examples in this thread that allow you to do something like:

var list = new List<SampleClass> ();
var sequence1 = list.OrderBy ("Property1");
var sequence2 = list.OrderBy ("Property2");
Community
  • 1
  • 1
Dan Abramov
  • 264,556
  • 84
  • 409
  • 511