C#中引用變量是否應該加ref?


看如下代碼:
 
void Test(T t);
void Test(ref T t);
當T是值類型的時候,很好判斷,第一種並不能改變方法外變量的值,需要第二種方法才可以。通過查看IL代碼,可以看到第二種方法是直接傳的原變量T的地址,這里並沒有發生裝箱行為(如果發生裝箱的話,會在堆中新建一個T變量,這也不會改變原來T變量的值,因此不成立)。
當T是引用類型的時候,第一種其實也相當於值傳遞,不過是原變量的地址給了t這個變量,最終操作的是同一個對象。而用ref的話,就沒有地址復制這一步,直接把原變量的地址傳了進去,當然結果都是一樣的。
 
*但如下情況需要注意的是
 
        static void Main(string[] args)
        {
            UserInfo info = new UserInfo();
            Console.WriteLine("調用方法之前哈希code:{0}", info.GetHashCode());
            Reset(info);
            Console.WriteLine("調用方法之后哈希code:{0}", info.GetHashCode());
            Console.ReadKey();
        }
 
        public static void Reset(UserInfo info)
        {
            Console.WriteLine("Reset賦值之前的哈希code:{0}", info.GetHashCode());
            UserInfo user = new UserInfo();
            info = user;
            Console.WriteLine("Reset賦值之后哈希code為{0}", info.GetHashCode());
        }

 

查看輸出:
 
可以看到,如果不使用ref,傳入的是 引用的一個副本,這個副本存儲的地址和傳入的變量是一致的,引用同一個對象,因此哈希值相同。
給這個副本賦新的變量地址后,哈希值發生了改變。
但這總歸是發生在復制的副本身上,原來的變量,哈希值未改變。
值得注意的是,如果info里面的參數,在Reset中info = user這個語句之后,發生了任何改變,都已經不會體現到Reset外圍。
比如info.userName = "aa";
在info = user語句之后,加入 info.userName = "cc"。
在最后Console.ReadKey之前輸出userName, 它還是"aa"。
Reset里面的info已經完全指向另外一個對象了。
 
如果我們在Reset方法的參數之前加上ref
 
那就是直接使用外圍變量的值了,任何操作都直接影響外圍傳入的變量。包括上述說的userName也會被改變。整個來說就是原來變量地址上的類被換了一個。
 
綜合來說,如果只是改變原有變量的內部變量值之類的操作,加不加ref都一樣,當涉及到new賦值操作的時候,除非是刻意需要這么做,不然推薦加ref。


免責聲明!

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



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