_ => dấu gạch dưới này có ý nghĩa gì trong biểu thức Lambda?


111

Biểu thức lambda _=> exprcó nghĩa là gì?

Mục đích của _làm đầu vào cho lambda là gì?

Thí dụ:

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

8
Xin chào và chào mừng bạn đến với StackOverflow. Tôi đã tự do chỉnh sửa câu hỏi của bạn một chút để tăng cơ hội nhận được câu trả lời hữu ích, hy vọng bạn không phiền.
Lasse V. Karlsen

Lưu ý rằng, giả sử listlà một IEnumerable<T>, họ có thể (và nên) đã chỉ được sử dụngsum = list.Count();
BlueRaja - Danny Pflughoeft

Tôi đoán điều này có thể được sử dụng để ngăn bạn "gây ô nhiễm" phạm vi bằng một tên biến mới có thể được sử dụng ở một nơi khác sẽ gây ra xung đột.
Tim Schmelter

Câu trả lời:


83

Đó là một quy ước được sử dụng khi bạn không quan tâm đến tham số.


3
Nó phổ biến hơn trong Haskell và các ngôn ngữ chức năng khác. Tôi nghĩ đó là nguồn gốc của nó.
Gabe Moothart

10
Trong Haskell, ML, Scala và những người khác, _là ký tự đại diện trong đối sánh mẫu. Về cơ bản nó có nghĩa là "Tôi không quan tâm, tôi luôn muốn điều này phù hợp". Sau đó, "Tôi không quan tâm" này được chuyển sang khi đặt tên cho những thứ mà bạn không quan tâm và từ đó, nó tràn sang các ngôn ngữ lập trình khác. Ví dụ, nó cũng được sử dụng trong Ruby để có nghĩa tương tự như trong ví dụ này, mặc dù _hoàn toàn không có ý nghĩa đặc biệt trong Ruby.
Jörg W Mittag

@ JörgWMittag Đúng vào tháng 5 năm 2010, nhưng không phải vào tháng 6 năm 2010. Thời điểm tuyệt vời! :) stackoverflow.com/q/6397078/38765
Andrew Grimm

38

Đó là một tên tham số, mặc dù không phải là một tên hữu ích, nhưng nó là tên thường được sử dụng (theo một số quy ước) khi bạn cần chỉ định rằng biểu thức một tham số để lấy mã để biên dịch, nhưng bạn không thực sự quan tâm về nó, vì vậy bạn sẽ bỏ qua nó.

Về cơ bản, nó khai thác cú pháp cho những gì một định danh hợp pháp trong C # cấu thành và vì một định danh có thể bắt đầu bằng dấu gạch dưới và không chứa gì khác, nó chỉ là một tên tham số.

Bạn có thể dễ dàng viết:

var _ = 10;

1
Thay vì _, chúng ta có thể sử dụng () không?
amesh

2
Bạn đã thử sử dụng nó?
Lasse V. Karlsen

Có, tôi đã sử dụng nó khi tôi tạo một chuỗi sử dụng biểu thức lambda. Thread t= new Thread(()=>doSomething(x,y)); t.start();
amesh

Những gì tôi giả định là, việc sử dụng _ là chuyển từng biến của bộ sưu tập sang biểu thức lambda mặc dù nó không được sử dụng. Nhưng khi chúng ta sử dụng () nó có thể không xảy ra. Ý tôi là tham số lambda ít hơn.
amesh

Bạn cần thử nó bằng cách gọi phương thức ForEach. Có một sự quá tải trên phương thức khởi tạo Thread nhận một đại biểu không nhận bất kỳ tham số nào. Hãy thử gọi một phương thức, chẳng hạn như ForEach, thay vào đó nhận một đại biểu nhận một tham số.
Lasse V. Karlsen


10

Bởi vì biểu thức lamda chủ yếu được sử dụng trong một đoạn mã ngắn, ẩn danh nên tên của biến đôi khi không cần thiết, thậm chí chúng không sử dụng biến trong khối mã, vì vậy chúng chỉ đưa ra một _ cho ngắn gọn, quy ước.


7

Tôi cũng thứ hai việc sử dụng _ => _.method()lambdas một dòng, gọi phương thức, vì nó làm giảm trọng lượng nhận thức của hướng dẫn. Đặc biệt khi sử dụng generic, việc viết x => x.method()chỉ thêm vào phần cân nhắc trong tích tắc "Đây là 'x' là gì? Nó có phải là một tọa độ trong không gian không?".

Hãy xem xét trường hợp sau:

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

Được sử dụng với lệnh gọi Generics, dấu gạch dưới trong trường hợp này hoạt động như một "biểu tượng bỏ qua". Nó tránh dư thừa, xác định rằng kiểu của đối số là hiển nhiên và có thể được suy luận khi sử dụng - giống như khi bạn sử dụng 'var' để ngăn việc lặp lại khai báo kiểu. Viết client=>client.Init()ở đây sẽ chỉ làm cho hướng dẫn dài hơn mà không thêm bất kỳ ý nghĩa nào cho nó.

Rõ ràng, điều này không áp dụng cho các tham số được truyền cho phương thức, phương thức này nên được đặt tên mô tả. Ví dụ.:Do( id=>Log(id) );

Việc sử dụng tham số một dấu gạch dưới cho các lệnh gọi phương thức hầu như không hợp lý khi sử dụng một khối mã thay vì một lớp lót, vì mã định danh lambda bị ngắt kết nối khỏi định nghĩa chung của nó. Nói chung, khi sử dụng lại cùng một số nhận dạng, hãy đặt tên mô tả cho nó.

Điểm mấu chốt là tính chi tiết chỉ hợp lý để phân định, đặc biệt là đối với lambdas, được tạo ra để đơn giản hóa việc tạo đại biểu ẩn danh ngay từ đầu. Trong mọi trường hợp, nên sử dụng cách hiểu thông thường, cân bằng giữa tính dễ đọc và tính ngắn gọn. Nếu biểu tượng chỉ là "móc nối" với chức năng thực thì một số nhận dạng ký tự hoàn toàn ổn. Đó là trường hợp với vòng lặp For và các chữ cái "i" và "j" làm chỉ mục.


2
+1 cho cách tiếp cận này! Tôi mặc dù tôi là người duy nhất sử dụng dấu gạch dưới trong lambdas để "giảm trọng lượng nhận thức" chứ không phải để cho thấy rằng thông số này không được sử dụng. Nó đọc dễ dàng hơn với các dấu gạch dưới, đặc biệt nếu có nhiều chuỗi và bạn có thể suy ra ngay loại, như thường xảy ra với các truy vấn LINQ!
Varvara Kalinina

3
Do(id => Log(id))tốt hơn nên viết tắt là Do(Log).
Aluan Haddad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.