2013-03-17 22 views
8

Tại sao có thể sửa đổi giá trị của trường readonly bằng cách sử dụng sự phản chiếu nhưng không phải giá trị của một const?Tại sao có thể thay đổi giá trị của một trường chỉ đọc chứ không phải của một const sử dụng sự phản chiếu?

class Program 
{ 
    static void Main(string[] args) 
    { 
     Foobar foobar = new Foobar(); 
     Console.WriteLine(foobar.foo);     // Outputs "Hello" 
     Console.WriteLine(Foobar.bar);     // Outputs "Hello" 

     var field = foobar.GetType().GetField("foo"); 
     field.SetValue(foobar, "World");    // Ok 
     field = foobar.GetType().GetField("bar"); 
     field.SetValue(foobar, "World");    // Throws FieldAccessException 

     Console.ReadKey(); 
    } 
} 

public class Foobar 
{ 
    public readonly string foo = "Hello"; 
    public const string bar = "Hello"; 
} 

Tôi đã đọc this answer vì vậy tôi hiểu nó cho phép để phá vỡ các quy tắc cho readonly nhưng tại sao không cho const trong trường hợp đó? Tôi chắc chắn có một lý do chính đáng nhưng tôi không thể hiểu được nó có thể là gì.

- Edit -

Khi tôi hãy nhìn vào đoạn code trên sử dụng ildasm, giá trị của lĩnh vực readonly được đặt ở thời gian biên dịch. Không phải trên lĩnh vực chính nó không giống như cho các const nhưng trong constructor của lớp. Vì vậy, tôi không chắc chắn để có được lý do tại sao người ta có thể được "ghi đè" nhưng không phải là một trong những khác.

Ý tôi là, ngay cả khi giá trị của const được "mã hóa cứng" trong nhị phân, là lý do không thể sửa đổi giới hạn kỹ thuật trong khung chính vì "nó đã được đặt" hoặc chỉ là một quyết định thiết kế. Tôi không thấy bất kỳ lý do tại sao có thể không có một số "ma thuật" một nơi nào đó sửa đổi các const vì nó làm nó cho readonly.

- Chỉnh sửa 2 -

Để thêm đến các câu trả lời được chấp nhận, đó cũng là this other answer đó là khá thú vị. Những gì tôi đã không nhận được ở nơi đầu tiên khi hỏi câu hỏi này là giá trị đằng sau constthực sự thay thế bất cứ nơi nào nó được sử dụng trong mã. Với tuyên bố này:

public const string Foo = "Hello"; 

viết sau

Console.WriteLine(Foo); 

tương đương với văn bản

Console.WriteLine("Hello"); 

Thật vậy mã của tôi

Console.WriteLine(foobar.foo); 
Console.WriteLine(Foobar.bar); 

được thay thế trong IL bởi

IL_0008: ldfld  string ConsoleApplication3.Foobar::foo 
IL_000d: call  void [mscorlib]System.Console::WriteLine(string) 
IL_0012: nop 
IL_0013: ldstr  "Hello" 
IL_0018: call  void [mscorlib]System.Console::WriteLine(string) 
+1

Xem thêm: [Sự khác biệt giữa const và chỉ đọc là gì?] (Http://stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-readonly) –

+0

@CodyGray Cảm ơn cho liên kết của bạn. Tôi không biết cách bộ nhớ được xử lý cho 'const' và tác động của nó đối với các hội đồng khác. Việc sửa đổi giá trị của 'const' có thể có tác động chưa biết đến các assembly khác mà tôi đoán. – Guillaume

Trả lời

9

Vì trường const được 'đặt' tại thời gian biên dịch, tức là trình biên dịch thay thế const bằng giá trị đã cho trong khi biên dịch. Kết quả là cách các giá trị const hoạt động, giá trị của chúng được sao chép vào mọi assembly sử dụng chúng. Trong khi đó, các trường readonly được đánh giá trong thời gian chạy.

+0

Khi tôi xem xét mã trong câu hỏi của tôi trong ildasm, giá trị của trường 'readonly' cũng được đặt ở thời gian biên dịch. Không phải trên chính trường đó, không giống như 'const' nhưng trong hàm tạo. Vì vậy, tôi vẫn không chắc chắn để có được lý do tại sao người ta có thể được "ghi đè" nhưng không phải là một trong những khác. – Guillaume

+0

@Guillaume bạn có thể vui lòng cập nhật câu hỏi của bạn để bao gồm các quan sát IL của bạn cho cả const và chỉ đọc. – ColinE

+0

@Guillaume những gì bạn có thể quan sát là tối ưu hóa trình biên dịch trong trường hợp này làm cho chỉ đọc của bạn xuất hiện giống như khai báo const của bạn. Bạn không thể phỏng đoán quá nhiều từ mã được biên dịch! – ColinE

2

Lý do là các hằng số được thay thế bằng giá trị trong suốt thời gian biên dịch. Nhưng các trường chỉ đọc thì không. Bạn có thể thiết lập một giá trị cho một trường chỉ đọc ở cả khai báo và/hoặc tại hàm tạo của lớp đó. Tôi mong bạn trả lời câu hỏi này.

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