• 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修饰后,两者使用的是同一块内存空间。

  • 相关阅读:
    dotnet run urls=http://*:8080
    内敛声明变量
    C#反射赋值(更新时用)
    mysql---auto_increment=10啥意思呢?
    vscode--代码折叠与展开
    联想启天M410台式机的清除BIOS密码
    AntD是什么?
    react-router-dom 中文文档
    Recoil是什么?
    sql server查看建表的创建代码?
  • 原文地址:https://www.cnblogs.com/lz32158/p/12923621.html
Copyright © 2020-2023  润新知