简体   繁体   中英

C# notation understanding Select(int.Parse)

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

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 :)

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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM