Como converter todas as strings em List <string> para minúsculas usando LINQ?

94

Eu vi um trecho de código ontem em uma das respostas aqui no StackOverflow que me intrigou. Era algo assim:

 List<string> myList = new List<string> {"aBc", "HELLO", "GoodBye"};

 myList.ForEach(d=>d.ToLower());

Eu esperava poder usá-lo para converter todos os itens de myList em minúsculas. No entanto, isso não acontece ... depois de executar isso, o invólucro em myList não é alterado.

Portanto, minha pergunta é se EXISTE uma maneira, usando expressões LINQ e Lambda, de iterar e modificar facilmente o conteúdo de uma lista de maneira semelhante a esta.

Obrigado, max

Max Schilling
fonte

Respostas:

181

Abordagem mais fácil:

myList = myList.ConvertAll(d => d.ToLower());

Não muito diferente do seu código de exemplo. ForEachfaz um loop na lista original enquanto ConvertAllcria uma nova que você precisa reatribuir.

Jason Bunting
fonte
4
Não é um método de extensão.
leppie
@leppie: Verdade, não é - boa pegada. Nesse caso, se preocupar se é um método de instância ou um método de extensão pode ser um pouco pedante, mas é definitivamente preciso. :)
Jason Bunting
E a corda é imutável: P
Sherlock
48

Isso ocorre porque ToLower retorna uma string em minúsculas em vez de converter a string original. Então, você quer algo assim:

List<string> lowerCase = myList.Select(x => x.ToLower()).ToList();
Ryan Lundy
fonte
1
Eu gosto mais dessa abordagem do que da resposta aceita porque você pode usar isso com qualquer IEnumerable <string>, não apenas List <string>.
Joshua Pech,
6
Esta solução também funciona no .NET Core, ConvertAll não existe no .NET Core.
Jonas,
3
[TestMethod]
public void LinqStringTest()
{
    List<string> myList = new List<string> { "aBc", "HELLO", "GoodBye" };
    myList = (from s in myList select s.ToLower()).ToList();
    Assert.AreEqual(myList[0], "abc");
    Assert.AreEqual(myList[1], "hello");
    Assert.AreEqual(myList[2], "goodbye");
}
Marcumka
fonte
3

ForEachusa Action<T>, o que significa que você poderia afetar xse não fosse imutável. Como xé a string, é imutável, portanto, nada que você faça com ele no lambda mudará suas propriedades. A solução da Kyralessa é sua melhor opção, a menos que você queira implementar seu próprio método de extensão que permite retornar um valor de substituição.

Michael Meadows
fonte
Faça mais pesquisas se não tiver certeza ... lembra de algo?
Patrick Desjardins
O erro é humano, o link que forneci tinha 3,5 em negrito e 2,0 em normal, não vi. Eu apaguei minha postagem ... um simples comentário seu teria sido suficiente. Você deseja downvote sem motivo, do que agora supor.
Patrick Desjardins
Embora eu esteja escrevendo isso quase um ano depois, e embora não seja Daok, direi por que sua resposta está "errada" - você disse "A solução de Kyralessa é sua melhor opção" quando não está - minha solução é mais limpa e mais claro.
Jason Bunting,
-1
var _reps = new List(); // with variant data

_reps.ConvertAll<string>(new Converter<string,string>(delegate(string str){str = str.ToLower(); return str;})).Contains("invisible"))
Uhlamurile
fonte