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