_ => ขีดล่างนี้หมายความว่าอย่างไรในนิพจน์แลมบ์ดา


111

แลมบ์ดาแสดงออกเช่น_=> exprหมายถึงอะไร?

จุดประสงค์ของการ_ป้อนข้อมูลไปยังแลมบ์ดาคืออะไร?

ตัวอย่าง:

int count = 0;
list.ForEach(_ => count += 1);

8
สวัสดีและยินดีต้อนรับสู่ StackOverflow ฉันใช้เสรีภาพในการแก้ไขคำถามของคุณเล็กน้อยเพื่อเพิ่มโอกาสในการได้รับคำตอบที่เป็นประโยชน์หวังว่าคุณจะไม่รังเกียจ
Lasse V.Karlsen

โปรดทราบว่าสมมติว่าlistเป็นIEnumerable<T>พวกเขาสามารถ(และควร)เพิ่งใช้sum = list.Count();
BlueRaja - Danny Pflughoeft

ฉันเดาว่าสิ่งนี้สามารถใช้เพื่อป้องกันไม่ให้คุณ "ก่อมลพิษ" กับขอบเขตด้วยชื่อตัวแปรใหม่ซึ่งอาจถูกนำไปใช้ที่อื่นซึ่งจะทำให้เกิดความขัดแย้ง
Tim Schmelter

คำตอบ:


84

นั่นคือหลักการที่ใช้เมื่อคุณไม่สนใจพารามิเตอร์


3
เป็นเรื่องปกติมากในภาษา Haskell และภาษาที่ใช้งานได้อื่น ๆ ฉันคิดว่ามันมาจากไหน
Gabe Moothart

10
ใน Haskell, ML, Scala และอื่น ๆ_เป็นอักขระตัวแทนในการจับคู่รูปแบบ มันเป็นพื้นหมายความว่า "ฉันไม่สนใจฉันเสมออยากให้เรื่องนี้ตรงกับ" จากนั้น "ฉันไม่สนใจ" นี้จะถูกนำไปใช้เมื่อพูดถึงการตั้งชื่อสิ่งที่คุณไม่สนใจและจากนั้นมันก็แพร่กระจายไปยังภาษาโปรแกรมอื่น ๆ ตัวอย่างเช่นใช้ใน Ruby เพื่อหมายถึงสิ่งเดียวกันกับในตัวอย่างนี้แม้ว่าจะ_ไม่มีความสำคัญเป็นพิเศษใน Ruby ก็ตาม
Jörg W Mittag

@ JörgWMittag True ในเดือนพฤษภาคม 2010 แต่ไม่ใช่ของเดือนมิถุนายน 2010 เวลาที่ยอดเยี่ยม! :) stackoverflow.com/q/6397078/38765
Andrew Grimm

38

เป็นชื่อพารามิเตอร์แม้ว่าจะไม่ใช่ชื่อที่มีประโยชน์ แต่เป็นชื่อที่มักใช้ (ตามข้อตกลงบางประการ) เมื่อคุณต้องการระบุว่านิพจน์มีพารามิเตอร์เพื่อรับโค้ดไปคอมไพล์ แต่คุณไม่สนใจจริงๆ เกี่ยวกับเรื่องนี้ดังนั้นคุณจะเพิกเฉยต่อมัน

โดยพื้นฐานแล้วเป็นการใช้ประโยชน์จากไวยากรณ์สำหรับสิ่งที่ตัวระบุทางกฎหมายใน C # ประกอบขึ้นและเนื่องจากตัวระบุสามารถเริ่มต้นด้วยขีดล่างและไม่มีสิ่งอื่นใดจึงเป็นเพียงชื่อพารามิเตอร์

คุณสามารถเขียนได้ง่ายๆ:

var _ = 10;

1
แทน _ เราสามารถใช้ () ได้หรือไม่?
amesh

2
คุณลองใช้ไหม
Lasse V.Karlsen

ใช่ฉันเคยใช้มันเมื่อฉันสร้างเธรดโดยใช้นิพจน์แลมบ์ดา Thread t= new Thread(()=>doSomething(x,y)); t.start();
amesh

สิ่งที่ฉันคิดคือการใช้ _ กำลังส่งผ่านตัวแปรแต่ละตัวของคอลเล็กชันไปยังนิพจน์แลมบ์ดาแม้ว่าจะไม่ได้ใช้ก็ตาม แต่เมื่อเราใช้ () มันอาจไม่เกิดขึ้น ฉันหมายถึงแลมด้าพารามิเตอร์น้อยกว่า
amesh

คุณต้องลองโดยใช้การเรียกวิธี ForEach มีโอเวอร์โหลดบนตัวสร้างเธรดที่ใช้ผู้รับมอบสิทธิ์ที่ไม่ใช้พารามิเตอร์ใด ๆ ลองเรียกเมธอดเช่น ForEach ที่ใช้ผู้รับมอบสิทธิ์ที่รับพารามิเตอร์แทน
Lasse V.Karlsen


10

เนื่องจากนิพจน์ lamda ส่วนใหญ่จะใช้ในรหัสสั้น ๆ ที่ไม่ระบุตัวตนดังนั้นบางครั้งชื่อของตัวแปรจึงไม่จำเป็นแม้ว่าจะไม่ได้ใช้ตัวแปรในบล็อกโค้ดก็ตามดังนั้นพวกเขาจึงให้ _ เป็นรูปแบบสั้น ๆ


7

ฉันยังใช้_ => _.method()lambdas หนึ่งบรรทัดเพื่อเรียกวิธีการเป็นครั้งที่สองเนื่องจากจะช่วยลดน้ำหนักการรับรู้ของคำสั่ง โดยเฉพาะอย่างยิ่งเมื่อใช้ generics การเขียนx => x.method()จะเพิ่มการพิจารณาเสี้ยววินาทีว่า "นี่คืออะไร" x "คือพิกัดในอวกาศหรือไม่"

พิจารณากรณีต่อไปนี้:

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

ใช้กับการเรียก Generics ขีดล่างในกรณีนี้จะทำงานเป็น "สัญลักษณ์บายพาส" หลีกเลี่ยงความซ้ำซ้อนโดยกำหนดว่าประเภทของอาร์กิวเมนต์นั้นชัดเจนและสามารถอนุมานได้จากการใช้งานเช่นเดียวกับเมื่อคุณใช้ 'var' เพื่อป้องกันการประกาศประเภทซ้ำ การเขียนclient=>client.Init()ที่นี่จะทำให้คำสั่งยาวขึ้นโดยไม่ต้องเพิ่มความหมายใด ๆ

เห็นได้ชัดว่าสิ่งนี้ไม่ได้ใช้กับพารามิเตอร์ที่จะส่งผ่านไปยังเมธอดซึ่งควรตั้งชื่อตามคำอธิบาย เช่น.:Do( id=>Log(id) );

การใช้พารามิเตอร์ขีดล่างเดียวสำหรับการเรียกเมธอดนั้นแทบจะไม่สมเหตุสมผลเมื่อใช้บล็อกของโค้ดแทนซับเดียวเนื่องจากตัวระบุแลมบ์ดาถูกตัดการเชื่อมต่อจากนิยามทั่วไป โดยทั่วไปเมื่อต้องใช้ตัวระบุเดียวกันซ้ำให้ตั้งชื่อที่สื่อความหมาย

บรรทัดล่างคือการใช้คำฟุ่มเฟือยเป็นสิ่งที่สมเหตุสมผลสำหรับการลดความสับสนโดยเฉพาะอย่างยิ่งสำหรับ lambdas ซึ่งสร้างขึ้นเพื่อลดความซับซ้อนของการสร้างผู้รับมอบสิทธิ์ที่ไม่ระบุตัวตนในตอนแรก ไม่ว่าในกรณีใดควรใช้สามัญสำนึกโดยให้สมดุลกับความชัดเจนและความกระชับ หากสัญลักษณ์เป็นเพียง "ตะขอ" สำหรับการทำงานจริงตัวระบุอักขระหนึ่งตัวก็ใช้ได้ดี นั่นคือกรณีที่มี For-loops และตัวอักษร "i" และ "j" เป็นตัวสร้างดัชนี


2
+1 สำหรับแนวทางนี้! แม้ว่าฉันจะเป็นคนเดียวที่ใช้เครื่องหมายขีดล่างใน lambdas เพื่อ "ลดน้ำหนักองค์ความรู้" และไม่ใช่เพื่อแสดงว่าไม่ได้ใช้พารามิเตอร์นี้ มันอ่านง่ายขึ้นด้วยการขีดล่างโดยเฉพาะอย่างยิ่งหากมีการผูกมัดจำนวนมากและคุณสามารถสรุปประเภทได้ทันทีเช่นเดียวกับกรณีของการสืบค้น LINQ!
Varvara Kalinina

3
Do(id => Log(id))Do(Log)ย่อที่ดีกว่า
Aluan Haddad
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.