tags:

views:

784

answers:

3

I'm struggling to get my head around LINQ and have come to the conclusion that searching through dozens of examples until I find one that is near to my own application in C# is not teaching me how to fish.

So back to the docs where I immediately hit a brick wall.

Can someone please help me decipher the Enumerable.Select method as presented here on msdn http://msdn.microsoft.com/en-us/library/bb548891.aspx and given as a tip by Intellisense?

Enumerable.Select(TSource, TResult) Method (IEnumerable(TSource>), Func(TSource, TResult))

Here is the same line broken down with line numbers if it helps to refer:

  1. Enumerable.Select
  2. (TSource, TResult)
  3. Method
  4. (IEnumerable(TSource>),
  5. Func
  6. (TSource, TResult))
+4  A: 

The way to think of Select is as mapping each element of a sequence. Hence:

Enumerable.Select<TSource, TResult>: the Select method is parameterised by its source and result types (the type of thing you are mapping and the type you are mapping it to)

IEnumerable<TSource>: the sequence of things to map

Func<TSource, TResult>: the mapping function, that will be applied to each element of the source sequence

The result being an IEnumerable<TResult>, a sequence of mapping results.

For example, you could imagine (as a trivial example) mapping a sequence of integers to the string representations:

IEnumerable<string> strings = ints.Select(i => i.ToString());

Here ints is the IEnumerable<TSource> (IEnumerable<int>) and i => i.ToString() is the Func<TSource, TResult> (Func<int, string>).

itowlson
Thanks for this detailed answer. Is the keyword "Method" just saying Enumerable.Select is a method?I guess I am asking how do I decipher any help line such as this?
David Smith
Yes, that's right. The title of the MSDN topic is telling you the name of the member, the kind (method, property, event, field) and, for overloaded methods, the signature of the overload you are looking at. (In the case of Enumerable.Select, there are two overloads, distinguished by their mapping function types.)
itowlson
A: 

I'm of the opinion that the later chapters of C# in Depth do a good job of explaining LINQ, and what it all means. Plus the rest of the book teaches a lof of other very useful C# knowledge.

Marc Gravell
Thanks Marc, I do have that book but I do not find it helpful. I'm sure it will make perfect sense once I understand the topics.
David Smith
@David: If Daniel's answer is clearer for you than C# in Depth, could you suggest which areas of C# in Depth should be changed to improve it? I'm starting to put together the second edition, so feedback like that would be very useful!
Jon Skeet
+3  A: 

It might help to look at the definition of this method in C#, from the MSDN article you refer to:

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

The <angle brackets> denote the type parameters for this generic method, and we can start to explore the purpose of the method simply by looking at what the type parameters are doing.

We begin by looking at the name of the generic method:

Select<TSource, TResult>

This tells us that the method called Select deals with two different types:

  • The type TSource; and
  • The type TResult

Let's look at the parameters:

  1. The first parameter is IEnumerable<TSource> source — a source, providing a TSource enumeration.
  2. The second parameter is Func<TSource, TResult> selector — a selector function that takes a TSource and turns it into a TResult. (This can be verified by exploring the definition of Func)

Then we look at its return value:

IEnumerable<TResult>

We now know this method will return a TResult enumeration.

To summarise, we have a function that takes an enumeration of TSource, and a selector function that takes individual TSource items and returns TResult items, and then the whole select function returns an enumeration of TResult.

An example:

To put this into concrete terms, lets say that TSource is of type Person (a class representing a person, with a name, age, gender, etc), and TResult is of type String (representing the person's name). We're going to give the Select function a list of Persons, and a function that, given a Person will select just their name. As the output of calling this Select function, we will get a list of Strings containing just the names of the people.

Aside:

The last piece of the puzzle from the original method signature, at the top, is the this keyword before the first parameter. This is part of the syntax for defining Extension Methods, and all it essentially means is that instead of calling the static Select method (passing in your source enumeration, and selector function) you can just invoke the Select method directly on your enumeration, just as if it had a Select method (and pass in only one parameter — the selector function).

I hope this makes it clearer for you?

Daniel Fortunov