2013-04-06 24 views
5

Tại sao các tập quán const được thay thế bằng các giá trị của chúng trong thời gian biên dịch nhưng sau đó vẫn được đưa vào hội đồng? Ít nhất đây là những gì IL DASM và Reflector cho thấy..NET const ảnh hưởng đến kích thước lắp ráp được biên dịch

Hiện tại tôi đang sử dụng const để xác định nhiều số ma thuật và chuỗi để dễ dàng thay đổi mã mà không ảnh hưởng đến hiệu suất thời gian chạy.

Bây giờ tôi biết rằng điều đó không ảnh hưởng đến bộ nhớ đã sử dụng nhưng nó vẫn ảnh hưởng đến kích thước lắp ráp được biên dịch, điều này rất quan trọng đối với các ứng dụng điện thoại di động.

Một bất lợi khác là người khác dễ hiểu số ma thuật hơn khi nhìn vào mã chưa được tháo rời.

Tôi thực sự quan tâm đến lý do tại sao trình biên dịch (Mono cũng như .NET) thực hiện chính xác điều này?

+0

có thể trùng lặp của [Sự khác nhau giữa const và chỉ đọc là gì?] (Http://stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-readonly) –

+1

Tôi không đồng ý với đề xuất trùng lặp ở trên. Câu hỏi này cụ thể hơn so với so sánh 'const' so với' readonly' đơn giản. – stakx

+1

Tôi đồng ý với sự bất đồng của stakx. – stfx

Trả lời

6

Hành vi này được chỉ định trong ECMA-335 standard (trong đó cả .NET và Mono đều đang triển khai). Trích dẫn từ phần II.22.9, "Constant":

Lưu ý rằng Constant thông tin không trực tiếp ảnh hưởng đến hành vi gian chạy, mặc dù nó có thể nhìn thấy qua Reflection (và do đó có thể được sử dụng để thực hiện các chức năng như rằng bằng cách cung cấp System.Enum.ToString). Các trình biên dịch kiểm tra thông tin này, tại thời gian biên dịch, khi nhập siêu dữ liệu, nhưng giá trị của hằng số chính nó, nếu được sử dụng, sẽ được nhúng vào luồng CIL mà trình biên dịch phát ra. Không có hướng dẫn CIL để truy cập bảng Constant khi chạy.

Đó là, const giá trị được "inlined" (có thể là bởi vì họ có thể, và vì lý do hiệu suất), nhưng được lưu giữ trong siêu dữ liệu vẫn để họ có thể được kiểm tra bởi trình biên dịch và các công cụ.

Nếu không có siêu dữ liệu đã được phát ra cho const -ness lĩnh vực, điều này sẽ có những hậu quả (có thể là số những người khác — đây chỉ là hai ví dụ):

  • Trình biên dịch hoặc các công cụ như Reflector không còn có thể phân biệt giữa các trường thông thường và các trường const.
  • Nếu bạn đã kiểm tra một trường bằng cách sử dụng System.Reflection, bạn sẽ không còn có thể sử dụng số FieldInfo.IsLiteral property.
+0

+1 để trích dẫn và giải thích tiêu chuẩn ECMA. –

+0

+1 Vẫn còn tôi không chắc chắn làm thế nào mà sẽ tăng lông mày vì tôi đã không mong đợi để tìm 'const' lĩnh vực thông qua Reflection. Ngoài ra amusingly 'System.Enum.ToString' có lẽ là thực hiện chậm nhất để có được đại diện chuỗi enum. Nhưng tôi đoán nếu ECMA nói như vậy .. – stfx

+0

@stfx: Tôi đã nhầm lẫn với phần cuối cùng của câu trả lời của tôi. Không phải là các trường 'const' sẽ không còn có thể phát hiện được thông qua siêu dữ liệu; bạn sẽ không thể phân biệt chúng với các trường thông thường. Tôi đã sửa chữa câu trả lời của mình. – stakx

2

Kích thước lắp ráp tăng lên về cơ bản là do trình biên dịch C# phát ra siêu dữ liệu bổ sung về const -ness.


Bạn mong đợi kết quả gì từ chương trình ngắn này?

class Program 
{ 
    public const int C = 0; 
    public  int F = 0; 

    static void Main(string[] args) 
    { 
     foreach (FieldInfo field in typeof(Program).GetFields()) 
     { 
      Console.WriteLine("{0}: IsLiteral = {1}", field.Name, field.IsLiteral); 
     } 
    } 
} 

Sản lượng thực tế là:

C: IsLiteral = True 
F: IsLiteral = False 

nào phù hợp với tờ khai trong nguồn C# chính xác: Hai lĩnh vực, một trong số họ const.

Bây giờ, giả sử trình biên dịch C# đã quyết định không phát ra siêu dữ liệu Constant.Sau đó, đầu ra sẽ là:

C: IsLiteral = False 
F: IsLiteral = False 

Mà rõ ràng là không đúng khi so sánh với mã nguồn C#, vì bây giờ cả hai lĩnh vực xuất hiện như phi const.

Cuối cùng, chúng ta hãy nói rằng biên dịch C# đã quyết định không phát ra bất kỳ siêu dữ liệu cho C ở tất cả (vì nó "inlines" giá trị của lĩnh vực anyway):

F: IsLiteral = False 

Đây cũng là không chính xác, vì phản ánh không còn báo cáo sự tồn tại của một trường rõ ràng là có trong mã nguồn C#. Ít nhất đối với tôi, đó sẽ là một thời điểm tốt cho một số người nuôi lông mày.

Các ví dụ ngược lại này phải làm rõ lý do tại sao việc siêu dữ liệu hoàn chỉnh được phát ra ngay cả đối với các trường const.

+0

Cảm ơn bạn đã làm rõ. Tôi sẽ thích hơn nếu chúng được xử lý tương tự như C++ #defines như trong thực tế không phải là trường, không được biên dịch, và phản ánh không trả lại chúng nhưng tôi đoán các nhà thiết kế muốn hỗ trợ phản chiếu đó;) – stfx

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