I am trying to understand LINQ and become confident at using it. What I am struggling with are the parameters asked for. Example:
var sortedWords = words.OrderBy(a=>a.Length)
words
is an array collection. OrderBy
's intellisense says:
Func<string, TKey> keyselector
A func
executes a method, and a string
is the value, TKey
a key.
In the example http://msdn.microsoft.com/en-us/vcsharp/aa336756.aspx#thenBySimple (ThenBy
- Comparer), we compare length by saying a => a.Length
. I understand that syntax, but how is that related to what the intellisense is asking for?
I tend to find the method signature and intellisense unreadable because of all the generics.
Thanks.
The type (as displayed by Intellisense) makes sense if you understand the nature of lambda expressions in .NET/C#. Otherwise, it can indeed seem a bit strange to the newcomer. Begin by considering that the type of keySelector, Func<TSource, TKey> is simply a delegate. Before C# 3.0, you would call such a method by passing a delegate as a parameter, for example:
IEnumerable<string> sortedWords = words.OrderBy(new Func<string, int>(mySelectorMethod));
where mySelectorMethod is the name of an ordinary method which takes a string as a parameter and returns an int. (As a side point, I suppose you could use anonymous delegates, but let's not go there for now.) Also, note that this example is purely illustrative, as LINQ is almost always used with .NET 3.5/C# 3.0 (though I believe it can be used with either/both .NET 2.0/C# 2.0 - someone correct me if I'm wrong). Since C# 3.0, methods can be defined inline as lambda expressions, which are intended to be used in precisely such circumstances as these. Read over the MSDN article on lambda expressions (linked above) if you want to get a proper introduction, but here I will simply describe the use in this specific context. As you state, your code (in C# 3.0) is something like the following:
var sortedWords = words.OrderBy(a => a.Length);
The part of the expression that is a => a.Length
is the lambda expression, which is really just shorthand for declaring a function inline. The syntax of lambda expressions is quite simple for the most part; to the left of the => the arguments are specified, generally in the form (arg1, arg2, arg3), but since there's only one in this case you can omit the brackets. To the right of the => is the expression that is the return value of the function (lambda expression more accurately). Alternatively you can enclose actual code with a return statement within { and } though this is usually unnecessary. What I believe the C# compiler does is recognises the parameter passed to OrderBy as a lambda expression and then compiles it into a function and creates and passes the delegate for you. Note that lambda expressions can also be converted to System.Linq.Expressions.Expression objects (accessible expression trees) instead of delegates, but this is a much less common usage. Anyway, there's a lot going on behind the scenes here, but hopefully this should at least clarify why the type is Func<TSource, TKey> and how it relates to the lambda expression. As I said, read up on MSDN if you want a deeper understanding of LINQ/lambdas/delegates...
a => a.Length
I understand that syntax, but how is that related to what the intellisense is asking for?
This chunk of code is a lambda expression. A lambda expression is a handy way of generating an Anonymous method (in this case), or a System.Linq.Expressions.Expression . Let's break it down by parts.
Func<string, object>
. The parameter for such a function is a string, so the compiler determines that a must be a string. The only thing the programmer needed to provide is a name.Now, consider this C# 2.0 ...
IEnumerable<string> sortedWords =
Enumerable.OrderBy(words, delegate(string a) {return a.Length;});
With the C# 3.0
IEnumerable<string> sortedWords = words
.OrderBy(a => a.Length);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With