TAGS :Viewed: 6 - Published at: a few seconds ago

[ reuse a method call inside Func/lambda expression ]

First let me say I'm not sure if the title of this question makes any sense, but I'm not sure how to word my problem.

I have a class defined as

public static class NaturalSort<T>

This class has a method

public static IEnumerable<T> Sort(IEnumerable<T> list, Func<T, String> field)

Basically it performs a natural sort on some list given a Func that returns the value to sort on. I've been using this for anything that I want to do a natural sort on.

Normally I would do something like

sorted = NaturalSort<Thing>.sort(itemList, item => item.StringValueToSortOn)

Now I have a case where the value I want to sort on isn't a field of the item, but is a call to some method

Something like

sorted = NaturalSort<Thing>.sort(itemList, item => getValue(item))

Now what if I getValue returns an object instead of a string. and I need to do some conditional logic to get to my string value

sorted = NaturalSort<Thing>.sort(itemList, item => getValue(item).Something == null ? getValue(item).SomethingElse : getValue(item).SomeotherThing)

This would work, except the call to getValue is expensive and I don't want to call it 3 times. Is there some way I can call it once inside the expression?

Answer 1

Yes, lambdas can have multiple lines of code.

item =>
  var it = getvalue(item);
  return it.Something == null ? it.SomethingElse : it.SomeotherThing;

Make sure you return a value in this syntax if using a Func<T> delegate, while this is handled implicitly in the short syntax, you have to do it yourself in the multi-line syntax.

Also, you should make your Sort method an extension method, you also don't need the type parameter on the class, simply use

public static IEnumerable<T> Sort<T>(this IEnumerable<T> list, Func<T, String> field)

Answer 2

@Femaref is 100%, i'm just wondering, why you wouldnt go with

sorted = NaturalSort<Thing>.sort(itemList, item => getValue(item))
         .Select(item => item.Something == null ? item.SomethingElse : item.SomeotherThing)