關於C#中readonly的一點小研究


可能園子里有不少文章已經說明了這個問題了,但是我在這里寫這篇博客只是寫寫自己的一些體會,也權當是整理歸納,高手莫見笑。

===============正文分割線==================

現在正在學《編譯原理》課,老師讓我們根據給出的語言定義自己開發一個編譯器,本人對C#還是比較熟悉的所以優先選擇C#作為開發工具。本人用的是VS2012配Resharper,這是一個很好用的代碼分析及重構的工具,簡化了不少工作,但也有些問題一直都搞不懂。例如,在這個類中,Resharper一直提示“將字段設為readonly”。

從字面上看,readonly即“只讀”的,這就造成了誤解,讓我誤以為readonly的變量是不可編輯的,因此一直沒敢用這條建議。

但是既然這么提示了,總應該是有道理的。因此我就查了很多資料,包括在園子里提問,在加上自己的一點研究,終於算是搞懂了意思。

例如我們這里有一個類

    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或反射改變內存的情況。但是在本文所說的環境下不必考慮。(2013-9-27 14:30修改)

所以,大膽放心的用readonly吧,這樣還可以防止不必要的再賦值,保證了這個對象的安全性。

PS:這樣的兩個類之間的關系事實上就是UML中的組合關系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM