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

C# 引用类型作为值参数和引用参数

上一篇:Windows 2008连接远程桌面遇到的bug


下一篇:windowsAPI函数