2009-01-15 12 views
6

Điều này đã được đề cập trong câu hỏi khác của tôi và tôi nghĩ rằng nó có thể hữu ích để thêm nó vào hồ sơ. Trong chương trình sau, trong đó, nếu có, của các đại biểu được xác định tại địa phương được lưu trữ giữa các cuộc gọi đến phương pháp làm việc thay vì được tạo ra từ đầu mỗi lần?(nếu có) đại biểu được xác định cục bộ nào được lưu trong bộ nhớ cache giữa các cuộc gọi phương thức?

namespace Example 
{ 
    class Dummy 
    { 
     public int age; 
    } 

    class Program 
    { 
     private int field = 10; 

     static void Main(string[] args) 
     { 
      var p = new Program(); 

      while (true) 
      { 
       p.Work(); 
      } 
     } 

     void Work() 
     { 
      int local = 20; 

      Action a1 =() => Console.WriteLine(field); 
      Action a2 =() => Console.WriteLine(local); 
      Action a3 =() => Console.WriteLine(this.ToString()); 
      Action a4 =() => Console.WriteLine(default(int)); 
      Func<Dummy, Dummy, bool> dummyAgeMatch = (l, r) => l.age == r.age; 

      a1.Invoke(); 
      a2.Invoke(); 
      a3.Invoke(); 
      a4.Invoke(); 
      dummyAgeMatch.Invoke(new Dummy() { age = 1 }, new Dummy(){ age = 2 }); 
     } 
    } 
} 

Trả lời

7

Dựa trên những gì Reflector cho thấy, cuối cùng hai (a4dummyAgeMatch) đều được lưu trữ bởi trình biên dịch MS C# 3.0 (trong các lĩnh vực được gọi là "CS $ <> 9_CachedAnonymousMethodDelegate5" và "CS $ <> 9_CachedAnonymousMethodDelegate6" trong xây dựng cụ thể của tôi).

Những người này có thể được lưu trong bộ nhớ cache, trong khi rõ ràng những người khác phụ thuộc vào các biến bị bắt.

Tôi không tin rằng hành vi được bắt buộc bởi thông số kỹ thuật, nhưng trình biên dịch Mono hoạt động theo cùng một cách (với các tên biến khác nhau).

5

Vâng, để trả lời câu hỏi cụ thể: hai câu hỏi cuối cùng là những câu hỏi duy nhất được lưu trong bộ nhớ cache, vì chúng không nắm bắt bất cứ điều gì. Bạn có thể thấy điều này trong phản xạ (nhưng nó không phải là đẹp). Tất nhiên, bạn có thể tinh chỉnh chúng để làm họ tái sử dụng bằng cách đi qua trong args:

Action<Program> a1 = p => Console.WriteLine(p.field); 
Action<int> a2 = i => Console.WriteLine(i); 
Action<Program> a3 = p => Console.WriteLine(p.ToString()); 
Action a4 =() => Console.WriteLine(default(int)); 
Func<Dummy, Dummy, bool> dummyAgeMatch = (l, r) => l.age == r.age; 

Và vượt qua this vào a1/a3, và local vào a2. Bởi vì không ai trong số họ trực tiếp nắm bắt bất cứ điều gì nữa, tất cả họ có thể được lưu trữ (CS$<>9__CachedAnonymousMethodDelegate5 thông qua CS$<>9__CachedAnonymousMethodDelegate9 cho tôi, ít nhất). Tất nhiên, sau đó họ mất khả năng gán lại biến (đã được ghi trước đó) trực tiếp, nhưng người ủng hộ FP sẽ không thích điều đó anyway ;-p Bạn luôn có thể chuyển giá trị được cập nhật trở lại dưới dạng giá trị trả về hoặc khai báo loại đại biểu với ref đối số (mặc dù tôi không khuyên dùng nó).

+0

Cảm ơn bạn - đó là cuốn tiểu thuyết! – xyz