2013-02-06 29 views
7

tôi đang trải qua Edulinq bởi Jon Skeet, và tôi đi qua đoạn mã sau, trang 23, trong đó ông thực hiện cơ chế bộ nhớ cache cho Empty() điều hành của LINQJon Skeet Edulinq - Rỗng Mảng Caching

private static class EmptyHolder<T> 
{ 
    internal static readonly T[] Array = new T[0]; 
} 

Câu hỏi của tôi là, làm thế nào điều này thực sự bộ nhớ cache biến Array?

Tùy chọn, Tính năng này hoạt động như thế nào trong CLR?

Chỉnh sửa: Cũng theo sau đó, anh đề cập đến có một cuộc nổi dậy chống lại một mảng. Tại sao mọi người không nên trả lại một mảng (ngay cả khi nó có kích thước 0?)?

+0

Giá trị của 'Array' được lưu cho các đời của ứng dụng sau khi 'EmptyHolder ' là đầu tiên được tham chiếu, do nó là tĩnh. – Matthew

Trả lời

12

Câu hỏi của tôi là, điều này thực sự làm thế nào để lưu biến biến Array?

CLR lưu trữ mỗi đối số loại. Về cơ bản, EmptyHolder<int> là một loại khác với EmptyHolder<string> v.v ... và trình khởi tạo kiểu được gọi (tự động, bởi CLR) một lần trên loại bê tông.

Vì vậy:

var x = EmptyHolder<string>.Array; // Needs to construct the empty string[] array 
var y = EmptyHolder<string>.Array; // No extra work! x and y have the same value 
var z = EmptyHolder<int>.Array; // This constructs an empty array for int[] 

tùy chọn, như thế nào nó hoạt động trong CLR?

Đó là chi tiết triển khai mà tôi không biết nhiều, tôi sợ. Nhưng về cơ bản đây là tất cả về cách CLR làm những việc :)

Edit: Ngoài ra sau đó, ông đề cập đến đã có một cuộc nổi dậy chống trả lại một mảng. Tại sao mọi người không nên trả lại một mảng (ngay cả khi nó có kích thước 0?)?

Vâng, đã có một lời nhận xét của:

Phương pháp mảng không phải là quá lớn: Mọi người sẽ sai phụ thuộc vào giá trị trả về là một mảng mặc dù điều này không được ghi nhận.

Cá nhân tôi không nghĩ rằng đó là một vấn đề, nhưng nó đã được thú vị để viết thực hiện thay thế :)

0

Mỗi khi bạn gọi EmptyHolder.Empty() cho lần đầu tiên cho T, bạn sẽ phải gọi hàm dựng tĩnh cho EmptyHolder.

Bây giờ có vẻ như không có hàm tạo tĩnh nào, đúng không? Sai rồi. Lớp học có thể được viết lại thành ...

private static class EmptyHolder<T> 
{ 
    static EmptyHolder<T>() 
    { 
     Array = new T[0]; 
    } 
    internal static readonly T[] Array; 

    public IEnum<T> Empty(); 
} 

Bây giờ, các lần chạy tiếp theo của Empty sẽ không gọi hàm tạo tĩnh (trừ khi sử dụng T khác).

Có thể là tôi có thể phê bình Jon Skeet, đây là một tối ưu hóa nhỏ để lo lắng.

+2

(Xin lỗi vì không bình luận trước điều này - Tôi chưa từng thấy câu hỏi này trước đây.) Chúng không giống nhau. Mã này có một hàm tạo tĩnh; mã của tôi không. Cả hai đều có kiểu khởi tạo, nhưng đó không phải là điều tương tự. Nó ảnh hưởng đến hiệu năng một chút, và loại bảo đảm nào có thời gian. http://csharpindepth.com/Articles/General/Beforefieldinit.aspx –