Co oznacza wyrażenie lambda _=> expr
?
Jaki jest cel _
wejścia do lambdy?
Przykład:
int count = 0;
list.ForEach(_ => count += 1);
list
to IEnumerable<T>
oni mogli (i powinny) być tylko używanesum = list.Count();
Co oznacza wyrażenie lambda _=> expr
?
Jaki jest cel _
wejścia do lambdy?
Przykład:
int count = 0;
list.ForEach(_ => count += 1);
list
to IEnumerable<T>
oni mogli (i powinny) być tylko używanesum = list.Count();
Odpowiedzi:
To jest konwencja używana, gdy nie zależy Ci na parametrze.
_
jest to znak wieloznaczny w dopasowywaniu wzorców. Zasadniczo oznacza to „Nie obchodzi mnie to, zawsze chcę, żeby to pasowało”. To „nie obchodzi mnie” jest następnie przenoszone, jeśli chodzi o nazywanie rzeczy, na których nie zależy, a stamtąd przenosi się do innych języków programowania. Na przykład jest również używane w języku Ruby w znaczeniu tego samego, co w tym przykładzie, mimo że _
nie ma absolutnie żadnego specjalnego znaczenia w języku Ruby.
Jest to nazwa parametru, choć nie jest użyteczna, ale jest zwykle używana (przez niektóre konwencje), gdy musisz określić, że wyrażenie ma parametr, aby kod został skompilowany, ale tak naprawdę cię to nie obchodzi o tym, więc po prostu to zignorujesz.
Zasadniczo wykorzystuje składnię dla tego, co stanowi identyfikator prawny w C #, a ponieważ identyfikator może zaczynać się od podkreślenia i nie zawierać nic więcej, jest to tylko nazwa parametru.
Mogłeś po prostu napisać:
var _ = 10;
Thread t= new Thread(()=>doSomething(x,y)); t.start();
_
jest prawidłową nazwą zmiennej. Po prostu używają _
jako zmiennej.
Popieram również użycie _ => _.method()
dla jednowierszowych lambd wywołań metody, ponieważ zmniejsza to wagę poznawczą instrukcji. Szczególnie, gdy używamy typów ogólnych, pisząc x => x.method()
po prostu dodajemy do rozważenia ułamek sekundy „Co to jest 'x'? Czy to współrzędna w przestrzeni?”.
Rozważ następujący przypadek:
Initialize<Client> ( _=>_.Init() );
Używany z wywołaniem typu Generics, podkreślenie w tym przypadku działa jak „symbol obejścia”. Unika redundancji, definiując, że typ argumentu jest oczywisty i można go wywnioskować z użycia - tak jak w przypadku użycia „var”, aby zapobiec powtarzaniu deklaracji typu. Pisanie client=>client.Init()
tutaj po prostu wydłużyłoby instrukcję bez nadawania jej znaczenia.
Oczywiście nie dotyczy to parametrów, które mają być przekazane do metody, które należy nazwać opisowo. Na przykład.:Do( id=>Log(id) );
Użycie pojedynczego parametru podkreślenia dla wywołań metod jest mało uzasadnione, gdy używa się bloku kodu zamiast jednowierszowego, ponieważ identyfikator lambda zostaje odłączony od jego definicji generycznej. Ogólnie rzecz biorąc, jeśli ten sam identyfikator ma być ponownie użyty, należy nadać mu opisową nazwę.
Najważniejsze jest to, że gadatliwość jest uzasadniona tylko dla ujednoznacznienia, zwłaszcza w przypadku lambd, które zostały stworzone przede wszystkim w celu uproszczenia tworzenia anonimowych delegatów. W każdym razie należy kierować się zdrowym rozsądkiem, równoważąc czytelność i zwięzłość. Jeśli symbol jest tylko „zaczepem” do rzeczywistej funkcjonalności, identyfikatory jednego znaku są w porządku. Tak jest w przypadku pętli For oraz liter „i” i „j” jako indeksatorów.
Do(id => Log(id))
jest lepiej skracany jako Do(Log)
.