_ => 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);

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.


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;

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


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


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.