tags:

views:

173

answers:

5

I got this linq example from msdns 101 linq examples:

public void Linq12() {
    int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

  var numsInPlace = numbers.Select((num, index) => new {Num = num, InPlace = (num ==     
  index)});

    Console.WriteLine("Number: In-place?");
    foreach (var n in numsInPlace) {
        Console.WriteLine("{0}: {1}", n.Num, n.InPlace);
    }
}

Here are my questions:

  1. What is the (num, index) part? Could these have been called anything such as a,b and can there be as many as I want?

  2. How does the compiler determine what the type the anonymous type is going to be?

  3. What is the => used for?

  4. Must there always be at least one parameter. For example, in the following linq query is n a parameter or this select different from the other one (Select(num,index))

    int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
    
    
    var numsPlusOne =
        from n in numbers
        select n + 1;
    }
    
+4  A: 

1) These are parameters being passed to the Func<TSource, Int32, TResult> used by this overload of Enumerable.Select.

What's happening is that the compiler automatically creates a lambda that passes a "<T>" from your enumerable as well as it's index to a function you're generating. You named it "num" and "index", "num" being the integer in your array, and "index" being the index into the array. You can name them anything, but they must exist in the Func being used by the Select method (in this case, there will always be two, and the second will be an int).

2) The compiler makes a NEW type for you. The anonymous type is just that - an anonymous type that's generated with properties corresponding to the types you assign within it, in this case, an int (Num) and a bool (InPlace). The types are determined by what's being set.

3) This is the Lambda Operator. It lets you create a lambda expression, which is a function, defined inline, with no name returning a single value.

4) In your second case, LINQ is calling the overload of Select which takes a Func<TSource,TResult>, so you only have one parameter. There are two versions of Enumerable.Select.

Reed Copsey
Great! Thanks for the nice explanation. I will have to parse through it some more. Sometimes these answers bring up new questions, if you know what I mean.
Xaisoft
@Xaisoft: just wait til you bump into closures (again)
Joel Coehoorn
lol, I actually have one more question regarding the query and will update my post.
Xaisoft
I just put in answers for your other two questions.
Reed Copsey
+1  A: 

(num, index) is used because the lambda expression has two parameters. You should be able to call these anything you want, but it is useful to call the second one "index" as a reminder of what it represents. In the case of Select, I believe that you can only use one or two parameters.

I'm afraid I can't really address your second question.

Edit: Regarding your new questions, "=>" is simply the syntax for a lambda expression. The expression to the left of this represents parameter(s) and the expression to the right of it represents the body of a function.

As far as I know, this:

var numsPlusOne =
 from n in numbers
 select n + 1;

Is the same as this:

var numsPlusOne = numbers.Select(n => n + 1);

The difference is only in the syntax (how it's written.)

Paul Williams
Thanks for the conversion. That helps.
Xaisoft
+1  A: 
  1. Yes, they can be called a or b; they are parameters used in the delegate.

  2. The compiler simply generates an anonymous type; that IS the type.

Gurdas Nijor
The compiler must give the anonymous type a type correct?
Xaisoft
Yes, it gives it a name; but that's an implementation detail.
Gurdas Nijor
+2  A: 

Could these have been called anything?

Yes

can there be as many as I want?

No. That's a signature for a function that has to match the selector argument for one the IEnumerable<T>.Select() overloads. From the docs:

The first argument to selector represents the element to process. The second argument to selector represents the zero-based index of that element in the source sequence.

.

How does the compiler determine what the type the anonymous type is going to be?

It makes up a new type on the spot. Well, sort of. The compiler makes up a new type, and even there it will occasionally re-use the made-up types.

What is the => used for?

It's the lambda operator (also known as the "wang" operator. really.). It tells the compiler you're building a lambda expression (basically, an in-line function).

Must there always be at least one parameter.

In this context, yes. You have to create an expression that matches the type expected by the selector parameter for the call to the Select() method. In other contexts, no. You can certainly do something like this:

Func<string> x = () => string.Empty;

is n a parameter or this select different from the other one

That select code will be translated by the compiler to use the same kind of IL as the select extension method. However, it's a different select because it's using a different overload.

Joel Coehoorn
+1  A: 

1
The (num, index) is the parameters in a lamda expression. It takes the form:

(parameters) => expression

The parentheses can be omitted if there is only one parameter:

parameter => expression

You can name the parameters anything you like that doesn't conflict with other variables in the scope.

There can be any number of parameters in a lambda expression (even zero), but when you use it in a call to a method, it has to match the signature of the delegate that the method expects.

2
The compiler doesn't determine a type for the anonymous class, it creates a new anonymous class that contains the properties that are set.

Guffa
So must there always be at least one parameter.
Xaisoft
@Xaisoft: No, you can have zero parameters, like this: () => expression.
Guffa