_ => o que esse sublinhado significa nas expressões Lambda?

111

O que significa uma expressão lambda como _=> expr?

Qual é a finalidade de _como entrada para lambda?

Exemplo:

int count = 0;
list.ForEach(_ => count += 1);
Prasad
fonte
8
Olá, bem-vindo ao StackOverflow. Tomei a liberdade de editar um pouco sua pergunta para aumentar sua chance de obter respostas úteis, espero que você não se importe.
Lasse V. Karlsen
Observe que, supondo que listseja um IEnumerable<T>, eles poderiam (e deveriam) apenas ter usadosum = list.Count();
BlueRaja - Danny Pflughoeft
Eu acho que isso pode ser usado para evitar que você "polua" o escopo com um novo nome de variável que pode ser usado em outro lugar, o que poderia causar um conflito.
Tim Schmelter

Respostas:

84

Essa é uma convenção usada quando você não se preocupa com o parâmetro.

ChaosPandion
fonte
3
É mais comum em Haskell e outras linguagens funcionais. Acho que é daí que vem.
Gabe Moothart
10
Em Haskell, ML, Scala e outros, _é o caractere curinga na correspondência de padrões. Basicamente, significa "Eu não me importo, sempre quero que combine". Esse "eu não me importo" é transportado quando se trata de nomear coisas com as quais você não se importa e, a partir daí, se espalha para outras linguagens de programação. É, por exemplo, também usado em Ruby para significar a mesma coisa que neste exemplo, embora não _tenha absolutamente nenhum significado especial em Ruby.
Jörg W Mittag
@ JörgWMittag Verdadeiro em maio de 2010, mas não em junho de 2010. Momento incrível! :) stackoverflow.com/q/6397078/38765
Andrew Grimm
38

É um nome de parâmetro, embora não seja útil, mas é o normalmente usado (por algumas convenções) quando você precisa especificar que a expressão tem um parâmetro para obter o código para compilar, mas você realmente não se importa sobre isso, então você simplesmente vai ignorá-lo.

Basicamente, ele explora a sintaxe do que constitui um identificador legal em C # e, como um identificador pode começar com um sublinhado e não conter mais nada, é apenas um nome de parâmetro.

Você poderia facilmente ter escrito:

var _ = 10;
Lasse V. Karlsen
fonte
1
Em vez de _, podemos usar ()?
amesh
2
Você tentou usar isso?
Lasse V. Karlsen
Sim, usei-o quando estava criando um thread usando a expressão lambda. Thread t= new Thread(()=>doSomething(x,y)); t.start();
amesh
O que presumo é que o uso de _ está passando cada variável da coleção para a expressão lambda, embora não seja usada. Mas quando usamos () isso pode não acontecer. Quero dizer parâmetro menos lambda.
amesh
Você precisa tentar usando a chamada de método ForEach. Há uma sobrecarga no construtor Thread que leva um delegado que não leva nenhum parâmetro. Tente chamar um método, como o ForEach, que usa um delegado que usa um parâmetro no lugar.
Lasse V. Karlsen
29

_é um nome de variável válido. Eles estão usando apenas _como uma variável.

BlueRaja - Danny Pflughoeft
fonte
10

Como a expressão lamda é usada principalmente em um código anônimo curto, de modo que o nome da variável às vezes não é necessário, mesmo que não usem a variável no bloco de código, eles apenas fornecem um _ para uma convenção curta

vodkhang
fonte
7

Também apoio o uso de _ => _.method()para lambdas de chamada de método de uma linha, uma vez que reduz o peso cognitivo da instrução. Especialmente ao usar genéricos, escrevendox => x.method() apenas adiciona aquela consideração de fração de segundo de "O que é este 'x'? É uma coordenada no espaço?".

Considere o seguinte caso:

Initialize<Client> ( _=>_.Init() );

Usado com uma chamada Genérica, o sublinhado neste caso funciona como um "símbolo de desvio". Isso evita redundância, definindo que o tipo do argumento é óbvio e pode ser inferido pelo uso - assim como quando você usa 'var' para evitar a repetição de uma declaração de tipo. Escrevendoclient=>client.Init() aqui apenas tornaria a instrução mais longa, sem adicionar nenhum significado a ela.

Obviamente, isso não se aplica aos parâmetros a serem passados ​​ao método, que devem ser nomeados de forma descritiva. Por exemplo.:Do( id=>Log(id) );

O uso do parâmetro de sublinhado único para chamadas de método dificilmente se justifica ao usar um bloco de código em vez de uma linha, uma vez que o identificador lambda é desconectado de sua definição genérica. Em geral, quando o mesmo identificador deve ser reutilizado, dê a ele um nome descritivo.

O resultado final é que a verbosidade só é justificável para desambiguação, especialmente para lambdas, que foram criados para simplificar a criação de delegados anônimos em primeiro lugar. Em qualquer caso, o bom senso deve ser usado, equilibrando legibilidade e concisão. Se o símbolo for apenas um "gancho" para a funcionalidade real, os identificadores de um caractere são perfeitamente adequados. Esse é o caso com loops For e as letras "i" e "j" como indexadores.

MaDDoX
fonte
2
1 para esta abordagem! Achei que fosse o único a usar sublinhados em lambdas para "diminuir o peso cognitivo" e não para mostrar que esse parâmetro não é utilizado. É mais fácil ler com sublinhados, especialmente se houver muito encadeamento e você puder inferir imediatamente o tipo, como costuma ser o caso com consultas LINQ!
Varvara Kalinina
3
Do(id => Log(id))é melhor abreviado como Do(Log).
Aluan Haddad