2009-04-17 28 views
12

Tôi đã reading this article about closures trong đó họ nói:Điều gì là đặc biệt về đóng cửa?

  • "tất cả các đường ống dẫn nước là tự động"
  • trình biên dịch "tạo ra một lớp wrapper" và "kéo dài tuổi thọ của các biến"
  • "bạn có thể sử dụng các biến địa phương mà không lo lắng"
  • trình biên dịch NET sẽ chăm sóc của các đường ống dẫn nước cho bạn, vv

vì vậy, tôi đưa ra một ví dụ dựa trên mã nguồn của họ và đối với tôi, nó có vẻ như mặc dù đóng cửa chỉ hoạt động tương tự như các phương thức được đặt tên thông thường mà còn "quản lý các biến cục bộ mà không cần lo lắng" và trong đó "tất cả các hệ thống ống nước là tự động".

Hoặc "vấn đề biến cục bộ" đã giải quyết vấn đề gì khiến cho việc đóng cửa trở nên đặc biệt/thú vị/hữu ích?

using System; 
namespace TestingLambda2872 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Func<int, int> AddToIt = AddToItClosure(); 

      Console.WriteLine("the result is {0}", AddToIt(3)); //returns 30 
      Console.ReadLine(); 
     } 

     public static Func<int, int> AddToItClosure() 
     { 
      int a = 27; 
      Func<int, int> func = s => s + a; 
      return func; 
     } 
    } 
} 

trả lời

Vì vậy, câu trả lời cho cái này là để đọc Jon Skeet's article on closures rằng Marc chỉ ra. Bài viết này không chỉ cho thấy sự tiến hóa dẫn đến các biểu thức lambda trong C# mà còn cho thấy cách các bao đóng được xử lý trong Java, một đọc tuyệt vời cho chủ đề này.

+0

Các ngôn ngữ khác (chẳng hạn như Javascript) hỗ trợ đóng cửa. Bạn đang hỏi về khái niệm hoặc thực hiện cụ thể của C#? – strager

+1

Tôi nghĩ rằng ví dụ quá đơn giản để hiểu được sức mạnh của việc đóng cửa. –

+0

@strager: Tôi có nghĩa là khái niệm nói chung, tôi đang cố gắng để có được đầu của tôi xung quanh các đại biểu, đóng cửa, bản đồ, lambdas, "biểu thức lambda", "cây lambda", chức năng ẩn danh, tách lạng bộ, vv và nói chung mới mô hình lập trình chức năng dường như mở rộng ra ngoài bất kỳ ngôn ngữ nào, có gốc rễ trong toán học, v.v. (Tôi đã đặt C# trong tiêu đề vì Stackoverflow giờ cho bạn biết rằng tiêu đề của bạn là "không đủ tốt, thêm từ duy nhất" ...) –

Trả lời

20

Ví dụ của bạn không rõ ràng và không (IMO) hiển thị việc sử dụng chụp điển hình (điều duy nhất được chụp là a, luôn là 3, vì vậy không phải là rất thú vị).

Xem xét việc này ví dụ text-book (một vị):

List<Person> people = ... 
string nameToFind = ... 
Person found = people.Find(person => person.Name == nameToFind); 

Bây giờ thử nó mà không có một kết thúc; bạn cần phải làm việc nhiều hơn, thậm chí nếu chúng ta lười biếng:

PersonFinder finder = new PersonFinder(); 
finder.nameToFind = ... 
Person found = people.Find(finder.IsMatch); 
... 
class PersonFinder { 
    public string nameToFind; // a public field to mirror the C# capture 
    public bool IsMatch(Person person) { 
     return person.Name == nameToFind; 
    } 
} 

Phương pháp chụp mở rộng hơn nữa để nhiều biến tại phạm vi khác nhau - một nhiều phức tạp đó là ẩn.

Khác với tên, ở trên là một xấp xỉ về những gì trình biên dịch C# thực hiện đằng sau hậu trường. Lưu ý rằng khi phạm vi bổ sung được tham gia, chúng tôi bắt đầu chuỗi các lớp chụp khác nhau (tức là phạm vi bên trong có tham chiếu đến lớp chụp của phạm vi bên ngoài). Khá phức tạp.

Jon Skeet có tốt article on this here và hơn in his book.

+0

(đối với câu hỏi đã xóa về cách đặt câu lệnh 'tĩnh'): Không - vì các chủ đề khác nhau có thể muốn tìm kiếm các tên khác nhau cùng một lúc hoặc trì hoãn việc thực hiện ủy nhiệm. –

+1

1 cho C# trong phần sâu vào đóng cửa –

+2

1 cho câu này trong C# trong bài viết đóng cửa Depth: "đóng cửa cho phép bạn đóng gói một số hành vi, vượt qua nó xung quanh giống như bất kỳ đối tượng khác, và vẫn còn được tiếp cận với bối cảnh trong mà chúng được tuyên bố lần đầu tiên là " –

0

Việc đóng là một chức năng của Trình biên dịch. Bạn không nhìn thấy nó, nó chỉ làm cho mã bạn viết công việc.

Nếu không có nó, lệnh gọi AddToIt (3) sẽ thất bại, vì lamda bên dưới sử dụng biến cục bộ a = 27 trong phạm vi AddToItClusure(). Biến này không tồn tại khi AddToIt được gọi.

Nhưng vì đóng cửa, một cơ chế được trình biên dịch sử dụng, mã hoạt động và bạn không phải quan tâm đến nó.

Các vấn đề liên quan