2016-12-03 14 views
73

Tôi đang tìm cách triển khai mới trong C# 7.0 và tôi thấy thú vị là chúng đã thực hiện các hàm cục bộ nhưng tôi không thể tưởng tượng một kịch bản có chức năng cục bộ được ưu tiên hơn biểu thức lambda. sự khác biệt giữa hai.Chức năng cục bộ vs Lambda C# 7.0

Tôi hiểu rằng lambdas là anonymous chức năng trong khi đó chức năng địa phương không được, nhưng tôi không thể hình dung ra một kịch bản thế giới thực, nơi chức năng địa phương có lợi thế hơn lambda biểu thức

Bất kỳ ví dụ sẽ được nhiều đánh giá cao. Cảm ơn.

+4

Generics, tham số ngoài, chức năng đệ quy mà không phải khởi tạo lambda thành null, v.v. –

+3

@KirkWoll - Bạn nên đăng câu trả lời này. – Enigmativity

Trả lời

137

This was explained by Mads Torgersen in C# Design Meeting Notes where local functions were first discussed:

Bạn muốn có một chức năng helper. Bạn chỉ sử dụng nó từ bên trong một hàm duy nhất, và nó có khả năng sử dụng các biến và các tham số kiểu nằm trong phạm vi trong hàm chứa đó. Mặt khác, không giống như một lambda bạn không cần nó như là một đối tượng lớp đầu tiên, vì vậy bạn không quan tâm để cung cấp cho nó một loại đại biểu và phân bổ một đối tượng đại biểu thực tế. Ngoài ra bạn có thể muốn nó được đệ quy hoặc chung chung, hoặc để thực hiện nó như là một iterator.

Để mở rộng trên đó một số chi tiết, những ưu điểm là:

  1. Performance.

    Khi tạo một lambda, một đại biểu phải được tạo ra, đó là một phân bổ không cần thiết trong trường hợp này. Các hàm cục bộ thực sự chỉ là các hàm, không có đại biểu nào là cần thiết. Ngoài ra, chức năng cục bộ hiệu quả hơn khi chụp các biến cục bộ: lambdas thường thu các biến vào một lớp, trong khi hàm cục bộ có thể sử dụng cấu trúc (được chuyển qua sử dụng ref), một lần nữa tránh phân bổ.

    Điều này cũng có nghĩa là gọi các hàm cục bộ rẻ hơn và chúng có thể được nội tuyến, có thể tăng hiệu suất hơn nữa.

  2. Chức năng cục bộ có thể đệ quy.

    Lambdas có thể đệ quy quá, nhưng nó đòi hỏi mã khó xử, nơi bạn lần đầu tiên gán null cho biến đại biểu và sau đó là lambda. Các hàm cục bộ có thể đệ quy tự nhiên (bao gồm cả đệ quy lẫn nhau).

  3. Chức năng cục bộ có thể là chung chung.

    Lambdas không thể chung chung, vì chúng phải được gán cho biến có loại cụ thể (loại đó có thể sử dụng biến chung từ phạm vi bên ngoài, nhưng không giống như vậy).

  4. Chức năng cục bộ có thể được triển khai dưới dạng trình lặp.

    Lambdas không thể sử dụng từ khóa yield return (và yield break) để triển khai IEnumerable<T> hàm trả về. Các hàm cục bộ có thể.

  5. Chức năng cục bộ trông đẹp hơn.

    Điều này không được đề cập trong báo giá trên và có thể chỉ là sự thiên vị cá nhân của tôi, nhưng tôi nghĩ cú pháp hàm bình thường trông đẹp hơn việc gán lambda cho biến đại biểu.Các hàm cục bộ cũng gọn gàng hơn.

    Hãy so sánh:

    int add(int x, int y) => x + y; 
    Func<int, int, int> add = (x, y) => x + y; 
    
+3

Rất rõ ràng, cảm ơn bạn đã dành chút thời gian để trả lời :) – Sid

+2

Tôi muốn thêm rằng các hàm cục bộ có tên tham số ở phía người gọi. Lambdas thì không. – Lensflare

+1

@Lensflare Đúng là tên thông số của lambda không được bảo tồn, nhưng đó là vì chúng phải được chuyển đổi thành đại biểu, có tên riêng. Ví dụ: 'Func f = (x, y) => x + y; f (arg1: 1, arg2: 1); '. – svick

37

Ngoài svick's great answer có một lợi thế hơn đối với chức năng địa phương:
Họ có thể được định nghĩa bất cứ nơi nào trong chức năng, ngay cả sau khi tuyên bố return.

public double DoMath(double a, double b) 
{ 
    var resultA = f(a); 
    var resultB = f(b); 
    return resultA + resultB; 

    double f(double x) => 5 * x + 3; 
} 
Các vấn đề liên quan