例如我們這里有一個類
class TestClass2 { private int someValue; public void ChangeValue(int newValue) { someValue = newValue; } public int ShowValue() { return someValue; } }
而在另一個類中使用它
class TestClass { private readonly TestClass2 tc; // 注意此處tc是readonly的 public TestClass() { tc = new TestClass2(); } public void ChangeTCValue(int value) { tc.ChangeValue(value); } public void Show() { Console.WriteLine("{0}", tc.ShowValue()); } }
我們看到雖然tc這個字段是readonly的,但是可以使用方法來改變tc中someValue的值。似乎這個“只讀”失去了意義,因為可以修改它的值的話還叫什么“只讀”呢?
非也!
從上面的代碼中我們可以看到,tc的類型是TestClass2,是一個引用類型。而引用類型是必須用new關鍵字為它分配了一塊內存以后它才能在后續代碼中工作的。也就是說,tc這個變量僅僅是一塊內存地址罷了。這里的“readonly” tc只是無法再重新更改它的引用,但它所引用對象的屬性是可以改變的。
那么為什么不用const呢?還是因為tc是引用,是動態分配內存的,不可能在編譯階段就確定它的地址,這點和值類型(包括string)是完全不一樣的。
綜上所述,可以得出結論:readonly修飾的字段,其初始化僅是固定了其引用(地址不能修改),但它引用的對象的屬性是可以更改的。
當然,這里的“地址不能修改”指的是在代碼中不能再對readonly變量進行再賦值,實際運行情況中可能會遇到GC或反射改變內存的情況。但是在本文所說的環境下不必考慮。
所以,大膽放心的用readonly吧,這樣還可以防止不必要的再賦值,保證了這個對象的安全性。