再聊一次值類型和引用類型
C#值類型,作為函數(shù)形參,形參被修改,不影響原值。
這是我們?cè)诔跏紝W(xué)習(xí)編程時(shí)需要記住的內(nèi)容,我們也是一直這樣踐行的。
先說結(jié)論:這是不準(zhǔn)確的。
為什么提出這樣看似很淺顯的問題,是因?yàn)橛写挝以谑褂肁rraySegment
這是一個(gè)托管的值類型,表示array的一個(gè)片斷, 在用做websocket接收數(shù)據(jù)的載體時(shí)我發(fā)現(xiàn)每次值傳遞后, 這個(gè)ArraySegment
我們做一個(gè)簡(jiǎn)單的實(shí)驗(yàn), 來證明【值類型作為函數(shù)形參, 形參被修改,不影響原值】不準(zhǔn)確。
- struct Slice
- {
- public Array Array { get; set; }
- public int Offset { get; set; }
- public int Count { get; set; }
- }
- class Program
- {
- static void Main(string[] args)
- {
- var slice = new Slice { Array = Array.CreateInstance(typeof(int), 5)};
- Test(slice);
- foreach(var i in slice.Array)
- {
- Console.WriteLine(i);
- }
- Console.ReadLine();
- }
- // 值類型傳參,值傳給tmp變量
- static void Test(Slice tmp)
- {
- tmp.Array.SetValue(1,1);
- tmp.Offset = 1;
- tmp.Count = 1;
- }
- }
- // 輸出 0 1 0 0 0
slice變量的引用類型屬性體現(xiàn)了變化,值類型Offset Count屬性不會(huì)變化。
這個(gè)簡(jiǎn)單的Demo告訴我們:
大部分情況下:“值類型作為函數(shù)形參,形參被修改,不影響原值”, 但是如果修改的是值類型的引用類型字段,原值類型照樣能體現(xiàn)修改。
歸根到底由值類型和引用類型的特性決定:
值類型的變量直接存儲(chǔ)數(shù)據(jù),而引用類型的變量持有的是數(shù)據(jù)的引用,數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)堆中;
寬泛地講:函數(shù)傳參,都是值傳遞(拷貝), 只是引用類型傳遞的是原對(duì)象的引用或地址值。