2013-03-13 1 views
6

У меня есть этот запрос LINQ:Как изменить только одно или два поля (-ов) в проекциях LINQ?

List<Customers> customers = customerManager.GetCustomers(); 

return customers.Select(i => new Customer { 
    FullName = i.FullName, 
    Birthday = i.Birthday, 
    Score = i.Score, 
    // Here, I've got more fields to fill 
    IsVip = DetermineVip(i.Score) 
}).ToList(); 

Другими словами, я хочу только один или два поля списка клиентов, которые будут изменены в зависимости от состояния, в моем методе бизнеса. У меня есть два способа сделать это,

  1. Использование for...each цикла, к перебрать клиентов и изменить это поле (императивный подход)
  2. Использование LINQ проекции (декларативный подход)

Есть ли любой метод, который будет использоваться в запросе LINQ, чтобы только изменить одно свойство в проекции? Например, что-то вроде:

return customers.Select(i => new Customer { 
    result = i // telling LINQ to fill other properties as it is 
    IsVip = DetermineVip(i.Score) // then modifying this one property 
}).ToList(); 

ответ

2

вы можете использовать

return customers.Select(i => { 
    i.IsVip = DetermineVip(i.Score); 
    return i; 
}).ToList(); 
+0

Остерегайтесь делать это, хотя вам нужно быть осторожным. Например, если вы делаете 'customer.FullName + =" foo "', и вы в конечном итоге перечисляете коллекцию дважды, вы получите некоторые довольно интересные результаты. –

1

Нет, Linq был разработан, чтобы перебрать коллекций, не затрагивая содержимое источника перечислимого.

Однако вы можете создать свой собственный метод для переборе и мутирует коллекции:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) 
{ 
    foreach(T item in enumeration) 
    { 
     action(item); 
    } 
} 

Вы можете использовать следующим образом:

return customers.ToList() 
       .ForEach(i => i.IsVip = DetermineVip(i.Score)) 
       .ToList(); 

Обратите внимание, что первый ForEach будет клонировать список источников.

1

Вы «можете», если вы создаете копию конструктора, который инициализирует новый объект со значениями существующего объекта:

partial class Customer 
{ 
    public Customer(Customer original) 
    { 
     this.FullName = original.FullName; 
     //... 
    } 
} 

Тогда вы можете сделать:

return customers.Select(i => new Customer(i) { IsVip = DetermineVip(i.Score)}) 
    .ToList() 

Но падение здесь, вы будете , создавая новый объект Customer на основе каждого существующего объекта, а не , изменяя существующий объект - вот почему я поставил «can» в кавычки. Я не знаю, действительно ли это то, чего вы желаете.

0

Как клиенты уже есть список, вы можете использовать метод ForEach:

customers.ForEach(c => c.IsVip = DetermineVip(c.Score)); 
2

В отличии от других ответов, вы можете изменить содержимое источника в LINQ по телефону метод в выражении Select (обратите внимание, что это не поддерживается EF, хотя это не должно быть проблемой для вас).

return customers.Select(customer => 
{ 
    customer.FullName = "foo"; 
    return customer; 
}); 
+0

Не уверен, но у меня тоже есть. Одно предостережение об этом, хотя вам нужно быть осторожным. Например, если вы делаете 'customer.FullName + =" foo "', и вы в конечном итоге перечисляете коллекцию дважды, вы получите некоторые довольно интересные результаты. –

+0

lc. возможно, вы ошибаетесь «клиент» для «клиентов». Предоставленное решение будет только перебирать коллекцию один раз. – Polity

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

  • Нет связанных вопросов^_^