1. 程式人生 > 其它 >C# 引用型別作為值引數和引用引數

C# 引用型別作為值引數和引用引數

  1. 引用型別作為值型別傳遞,形參和實參其實是兩個指標,只不過指向的是同一塊記憶體。新new一個物件是,它們兩的聯絡就被切斷了,指向了不同的記憶體塊。
  2. 引用型別作為引用引數,此時的形參其實是實參的一個別名,它們兩個其實是一個指標,新new一個物件是,指向的還是同一記憶體塊,因為它們本身就是同一個指標。

兩種情況的最後指向是不一樣的。

以下情況是, 在方法內建立一個新物件並賦值給形參。

引用型別作為值引數

using System;

namespace RefParameter
{
    class MyClass
    {
        public int test = 20;
    }
    
    class Program
    {
       static private void RefparameterTest( MyClass mc)
        {
            mc.test = 50;
            Console.WriteLine("修改值之後:{0}", mc.test);
            mc = new MyClass();
            Console.WriteLine("新建立之後:{0}", mc.test);
            
        }
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            Console.WriteLine("原始值:{0}\n=======", mc.test);
            RefparameterTest( mc);
            Console.WriteLine("=======\n最後值:{0}", mc.test);
            Console.ReadKey();

        }

    }
}

輸出:

原始值:20
=======
修改值之後:50
新建立之後:20
=======
最後值:50   // 被修改

引用型別作為引用引數

using System;

namespace RefParameter
{
    class MyClass
    {
        public int test = 20;
    }
    
    class Program
    {
       static private void RefparameterTest(ref MyClass mc)
        {
            mc.test = 50;
            Console.WriteLine("修改值之後:{0}", mc.test);
            mc = new MyClass();
            Console.WriteLine("新建立之後:{0}", mc.test);
            
        }
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            Console.WriteLine("原始值:{0}\n=======", mc.test);
            RefparameterTest(ref mc);
            Console.WriteLine("=======\n最後值:{0}", mc.test);
            Console.ReadKey();

        }
    }
}

輸出:

原始值:20
=======
修改值之後:50
新建立之後:20
=======
最後值:20 // 是新 new 物件的預設值 20

如果不在方法內部改變引用形參的指向,他們操縱的記憶體區域是一樣的,結果也是一樣的。

using System;


namespace RefTest
{
    class Myclass
    {
        public int val = 10;
    }


    class Program
    {

        static void Mymethod(Myclass a,  int b)  // 看這裡
        {
            a.val += 5;
            b += 5;
        }

        static void Main()
        {
            Myclass a = new Myclass();
            int b = 20;

            Console.WriteLine($"呼叫前:a = {a.val}, b = {b}");

            Mymethod(a,  b);  // 看這裡
            Console.WriteLine($"呼叫後:a = {a.val}, b = {b}");

            Console.ReadKey();
        }
    }
}

輸出:

呼叫前:a = 10, b = 20
呼叫後:a = 15, b = 20  // 可見 物件a的數值成員值改變了,值變數b沒有改變。
using System;


namespace RefTest
{
    class Myclass
    {
        public int val = 10;
    }


    class Program
    {

        static void Mymethod(ref Myclass a,  ref int b)  // 看這裡
        {
            a.val += 5;
            b += 5;
        }

        static void Main()
        {
            Myclass a = new Myclass();
            int b = 20;

            Console.WriteLine($"呼叫前:a = {a.val}, b = {b}");

            Mymethod(ref a,  ref b);  // 看這裡
            Console.WriteLine($"呼叫後:a = {a.val}, b = {b}");

            Console.ReadKey();
        }
    }
}

輸出:

呼叫前:a = 10, b = 20
呼叫後:a = 15, b = 25   // 可見 都改變了。


參考: 《C#圖解教程》 -> P66