30.值传递和引用传递

值传递

namespace Demo {

    

    class Program {

        static void Main(string[] args) {

            int n1 = 10;
            int n2 = n1;
            n2 = 20;
            Console.WriteLine(n1);
            Console.WriteLine(n2);          
            Console.ReadKey();
           
        }


    }

}

debug调式:

通过debug可以发现n1和n2地址值并不相同,它们在栈中空间也就不相同。

其栈中执行如图所示:

int n1 = 10;在栈中开辟一块空间n1,并赋值为10,int n2 = n1;就相当于在栈中开辟一块空间n2,并将n1的值复制一份赋给n2,这时n2的值为10,当将n2赋值为20时( n2 = 20;),就会将原值变为20.

下例代码中,num为10,调用Test方法将num传入其中进行+10操作,最后打印num值发现num值并没有改变。

namespace Demo {

    

    class Program {

        static void Main(string[] args) {

            int num = 10;
            Test(num);            
            Console.WriteLine(num);        
            Console.ReadKey();
           
        }

        public static void Test(int n) {
            n += 10;
        }


    }

}

运行结果:

内存图:

int num = 10;在栈中开辟了一块空间,并赋值为10,调用Test方法并传入num,会在栈中开辟一块命名为n的内存空间,并将num的值赋给了n,当执行方法中的+10操作时,是对命名为n的空间进行操作,将其值加10并没有对num进行改变,所以打印的仍然为10。

debug调试:

发现num和n的栈中地址不相同,内存空间并不是同一个。

引用传递

namespace Demo {

    

    class Program {

        static void Main(string[] args) {

            Person p1 = new Person();
            p1.Name = "张三";

            Person p2 = p1;
            p2.Name = "李四";

            Console.WriteLine(p1.Name);        
            Console.ReadKey();
           
        }


    }

    class Person {
        private string _name;

        public string Name {
            get;
            set;
        }
    }

}

运行:

简化内存图:

debug调试:

内存图:

当new Person()会在堆中开辟一块空间,并将此空间的地址值赋给p1,当将p1赋值给p2时,就会将引用(地址值)复制一份赋给p2,,p2就指向了堆中new Person()空间,当p2.Name="李四"时,也就相当于改变了本来Name的值,将Name从张三变为了李四。这时再通过打印p1.Name就会发现值变为了李四,因为两者使用的是同一块空间。

下例代码:

namespace Demo {

    class Program {

        static void Main(string[] args) {

            Person p = new Person();
            p.Name = "张三";

            Test(p);

            Console.WriteLine(p.Name);        
            Console.ReadKey();
           
        }

        public static void Test(Person person) {
            person.Name = "李四";
        }

    }

    class Person {
        private string _name;

        public string Name {
            get;
            set;
        }
    }

}

运行:

内存图:

当new Person()会在堆中开辟一块空间,并将此空间的地址值赋给p,当调用Test方法传入p的引用(地址值),就相当于将p的地址复制一份赋给person,person就指向了堆中new Person()空间,当person.Name="李四"时,也就相当于改变了本来Name的值,将Name从张三变为了李四。这时再通过打印p.Name就会发现值变为了李四,因为使用的是同一块空间。

debug调式:

通过debug会发现,两者在堆内存中的地址一样,使用的是通一块空间。

ref

namespace Demo {

    

    class Program {

        static void Main(string[] args) {

            int num = 10;
            Test(ref num);            
            Console.WriteLine(num);        
            Console.ReadKey();
           
        }

        public static void Test(ref int n) {
            n += 10;
        }


    }

}

运行:

我们发现当使用ref关键字后,它们使用的是同一块内存空间,所以对于num的值,在方法中对n进行+10操作,也就相当于对num进行+10操作,因为两者是同一块内存空间。

debug调试:

通过调式可以发现两者的栈中内存地址是一样的,也就是说被ref修饰后,两者使用的是同一块内存空间。

原文地址:https://www.cnblogs.com/lz32158/p/12923621.html