2014-10-23 1 views
4

Я немного озадачен поведением этого оператора select LINQ. Ниже комментариев LOOK HERE вы можете увидеть инструкцию LINQ. Этот оператор выбора находится в коллекции employees. Таким образом, он должен принимать только x в качестве входного параметра. Из любопытства я передал делегату i, и он работает. Когда он выполняет итерацию с помощью выбора, он сначала назначает 0, а затем увеличивается на 1. Результат можно увидеть в конце этого сообщения.Где «i» получает свое значение в этой инструкции LINQ?

Где переменная i получает свое значение? Прежде всего, почему это позволяет мне использовать переменную i, которая нигде не входит в сферу действия. Он не находится в глобальном масштабе ни в локальном методе Main. Любая помощь ценится, чтобы понять эту тайну.

namespace ConsoleApplication 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 

    public class Employee 
    { 
     public int EmployeedId { get; set; } 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var employees = new List<Employee>() 
           { 
            new Employee() { FirstName = "John", LastName = "Doe" }, 
            new Employee() { FirstName = "Jacob", LastName = "Doe" } 
           }; 

      // LOOK HERE... 
      var newEmployees = employees.Select((x, i) => new { id = i, name = x.FirstName + " " + x.LastName }); 

      newEmployees.ToList().ForEach(x => { Console.Write(x.id); Console.Write(" "); Console.WriteLine(x.name); }); 

      Console.ReadKey(); 
     } 
    } 
} 

В результате

enter image description here

0 John Doe 
1 Jacob Doe 

ответ

5

Enumerable.Select имеет перегрузку, которая выступает текущий индекс элемента в последовательности. Также Enumerable.Where и Enumerable.SkipWhile/TakeWhile имейте это. Вы можете использовать его как переменную цикла в for -loop, что иногда удобно.

Один пример, который использует индекс для создания анонимного типа для группы длинный список на группы по 4:

var list = Enumerable.Range(1, 1000).ToList(); 

List<List<int>> groupsOf4 = list 
    .Select((num, index) => new { num, index }) 
    .GroupBy(x => x.index/4).Select(g => g.Select(x => x.num).ToList()) 
    .ToList(); // 250 groups of 4 

или один с Where, который только выбирает даже показатели:

var evenIndices = list.Where((num, index) => index % 2 == 0); 

It также может быть важно упомянуть, что вы можете использовать эти перегрузки, которые проектируют индекс только в синтаксисе метода. LINQ query-syntax не поддерживает его.

+1

Стоит отметить: вероятно, это хорошая идея назвать этот параметр «лямбда-параметра», поскольку от кода совсем не ясно, что происходит (это своего рода скрытая функциональность). Даже документация немного туповата. –

+1

@RobertHarvey: Хороший момент, я добавил пример. –

Смежные вопросы