8

I found a little script that I understand fully. I've got a string with "1 -2 5 40" for example. It reads the input string, splits it into a temporary array. Then this array is parsed and each element is transformed into an integer. The whole thing is order to give the nearest integer to zero.

But what I don't understand is the notation Select(int.Parse). There is no lambda expression here and the method int.Parse isn't called with brackets. Same with the OrderBy(Math.Abs)

Thank you in advance =)

var temps = Console.ReadLine().Split(new []{' '}, StringSplitOptions.RemoveEmptyEntries);  

var result = temps.Select(int.Parse)
.OrderBy(Math.Abs)
.ThenByDescending(x => x)
.FirstOrDefault();
Angecroft
  • 81
  • 1
  • 3

5 Answers5

12

int.Parse is a method group - what you're seeing is a method group conversion to a delegate. To see it without LINQ:

Func<string, int> parser = int.Parse;
int x = parser("10"); // x=10

It's mostly equivalent to:

Func<string, int> parser = text => int.Parse(text);

... although there are plenty of differences if you want to go into the details :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
7

Select(int.Parse) is nearly equivalent to Select(x => int.Parse(x)).

The Select demands an Func<T, R>, which in this case is also the signature of int.Parse (it has a single parameter with a return value). It convers the method group to the matching delegate.

In this case Func<T, R> will map to Func<string, int>, so it matches the int Parse(string) signature.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
0

int.Parse is a method with signature string -> int (or actually, a method group, with different signatures. But the compiler can infer you need this one, because it is the only one that fits.

You could use this method as a parameter wherever you would supply a delegate parameter with the same signature.

realbart
  • 3,497
  • 1
  • 25
  • 37
0

The parameter for .Select() is Func<T1, T2>() where T1 is the input parameter (the individual values of temps), and T2 is the return type.

Typically, this is written as a lambda function: x => return x + 1, etc. However, any method that fits the generic definitions can be used without having to be written as a lambda since the method name is the same as assigning the lambda to a variable.

So Func<string, int> parseInt = s => Convert.ToInt32(s); is syntactically equivalent to calling the method int.Parse(s).

The language creates the shortcut of automatically passing the Func parameter to the inside method to create more readable code.

krillgar
  • 12,596
  • 6
  • 50
  • 86
0

Select LINQ IEnumerable<> extension method signature looks like that:

public static IEnumerable<TResult> Select<TSource, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, TResult> selector
)

Look at the selector argument. In your case you pass to Select .Net standard function int.Parse which has signature:

public static int Parse(
    string s
)

.Net compiler can convert delegates to Func<...> or Action<...>. In case of int.Parse it can be converted to Func and therefore can be passed as argument to Select method.

Exactly the same with OrderBy. Look at its signature too.

pkuderov
  • 3,501
  • 2
  • 28
  • 46