Por exemplo, dada a classe abaixo.
public class Customer { public string Name { get; set; } public DateTime ExpirationDate { get; set; } public bool IsActive { get; set; } }
E também uma lista genérica de objetos dessa classe.
var lista = new List<Customer> { new Customer { Name = "Ari Raimundo", ExpirationDate = new DateTime(2010, 4, 13), IsActive = true}, new Customer { Name = "Michael Jordan", ExpirationDate = new DateTime(1998, 12, 11), IsActive = true}, new Customer { Name = "Anfernee Hardaway", ExpirationDate = new DateTime(1995, 5, 5), IsActive = true}, new Customer { Name = "LeBron James", ExpirationDate = new DateTime(2009, 9, 7), IsActive = true} };
É possível usando o LINQ To Objects desativar, ou seja, alterar a propriedade IsActive para False, todos os clientes cuja data de expiração (ExpirationDate) for anterior à 2010?
Uma solução seria fazer uma consulta com a condição da data de expiração e então realizar um loop no resultado da consulta alterando a propriedade IsActive.
var r = lista.Where(c => c.ExpirationDate.Year < 2010); foreach (var customer in r) customer.IsActive = false;
Mesmo assim, uma parte do código não utiliza LINQ To Objects.
Podemos melhorar essa solução e ainda reutilizar nosso código em outras aplicações criando um método de extensão para a interface IEnumerable<T>. Esse método poderia se chamar UpdateAll e possuir um parâmetro Action<T>, ou seja, um delegate que encapsula uma ação qualquer.
Segue abaixo o código para o método.
public static class LINQToObjectExtensions { public static void UpdateAll<T>(this IEnumerable<T> source, Action<T> action) { foreach (var item in source) action(item); } }
Agora fica mais simples realizar a atualização baseada na condição.
lista.Where(c => c.ExpirationDate.Year < 2010)
.UpdateAll(c => c.IsActive = false);
Podemos também sobrecarregar o método de extensão e adicionar a condição como parâmetro.
public static void UpdateAll<T>(this IEnumerable<T> source, Func<T, bool> condition, Action<T> action) { var r = source.Where(condition); foreach (var item in r) action(item); }
Com isso, a atualização ficaria da seguinte maneira.
lista.UpdateAll(c => c.ExpirationDate.Year < 2010, c => c.IsActive = false);
Conforme comentei anteriormente, a vantagem dessa abordagem é que os métodos de extensão podem ser reutilizados em outras aplicações.
Os métodos foram baseados na thread abaixo do site Stack Overflow.
Update all objects in a collection using Linq
http://bit.ly/a5zUCe
Espero que tenham gostado.
Extension Methods (C# Programming Guide)
http://bit.ly/bjhbHe
LINQ To Objects
http://bit.ly/8OHCr3
Pessoal,
ResponderExcluirAcho que não fui muito feliz em colocar o nome do método como UpdateAll. Talvez ForEach seria melhor, já que o método poderia ser utilizado para outras razões.
Por exemplo, poderíamos utilizar o método para uma lógica de negócio qualquer, não necessariamente que atualizasse os objetos.
Até mais.
Olá Ari,
ResponderExcluirE porque não utilizar o próprio método ForEach que já existe na classe List<>?
lista.ForEach(c => c.IsActive = false);
Abraços,
Caio Proiete
http://caioproiete.com
Oi Caio,
ResponderExcluirNa verdade não fui muito feliz com o título do post. Realmente a classe List<> possui o método ForEach, mas a idéia seria alterar os objetos com base em uma condição.
Quando utilizo o Where no List<> o retorno é um IEnumerable<>, que não possui o método ForEach. Uma opção seria fazer assim:
lista.Where(c => c.ExpirationDate.Year < 2010).ToList().ForEach(c => c.IsActive = false);
Mas eu quis brincar um pouco com os métodos de extensão.
Obrigado pelo feedback.
Um abraço.