目录
一、须知概念
1.值类型:
2.引用类型:
二、ref
1.传值参数→值参数
2.传值参数→引用类型,并且创建新对象
3.传值参数→引用类型,只操作对象,不创建新对象
4.引用参数→值参数
5.引用参数→引用类型,并且创建新对象
6.引用参数→引用类型,不创建新对象只改变对象值
一、须知概念
1.值类型:
结构体类型、枚举类型
值类型在内存中存在栈中,根据变量的类型不同,在栈中分配响应的字节。
2.引用类型:
类、接口、委托
引用类型在内存中的存储分为两个部分。string x=new string(); 创建一个对象首先会在内存栈中分配4个字节用来存储该对象在堆中存放的地址,然后根据对象成员类型在堆中分配对应的空间存储对象,获得一个堆中内存的地址存放在栈中分配的四个字节中。
二、ref
1.传值参数→值参数
图片解释:(来自刘铁猛C#入门视频)
代码示例:
static void Main(string[] args)
{
Student stu=new Student();
int x=100;
stu.Add(x);
Console.WriteLine(x);//打印 100
}
class Student
{
public void Add(int x)
{
x = x + 1;
Console.WriteLine(x);//打印 101
}
}
打印预览:
从代码示例中可以看到,当我们使用传值参数时在方法中对值类型 形参x 增加时,并不会影响到实参x,因为在传递传值参数→值类型的时候是在内存中开辟一个新的地址把实参拷贝过去,当我们对形参进行修改其实是对拷贝的数据修改,不会影响到实参。
2.传值参数→引用类型,并且创建新对象
图片解释:(来自刘铁猛C#入门视频)
代码示例:
static void Main(string[] args)
{
Student stu = new Student() { Name = "张三" };
//打印Name:李四,Hash:58225482
MetHodTest(stu);
//打印Name:张三,Hash:54267293
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
static void MetHodTest(Student stu)
{
stu = new Student() { Name = "李四" };
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
class Student
{
public string Name { get; set; }
}
打印预览:
从代码示例中可以看到, 当我们使用传值参数时在方法中对引用类型 形参stu 创建一个新对象时并不会影响 实参stu 的值,因为当形参是引用类型的时候,我们把实参传递过去的时候在内存中其实是开辟一个新的空间,把实参对象在堆中的内存地址拷贝过去了,然后往形参上创建对象,创建的对象内存地址是保存在拷贝的栈中内存空间,所以不会影响实参。
3.传值参数→引用类型,只操作对象,不创建新对象
图片解释:(来自刘铁猛C#入门视频)
代码示例:
static void Main(string[] args)
{
Student stu = new Student() { Name = "张三" };
//打印Name:李四,Hash:58225482
MetHodTest(stu);
//打印Name:李四,Hash:58225482
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
static void MetHodTest(Student stu)
{
stu.Name = "李四";
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
class Student
{
public string Name { get; set; }
}
打印预览:
从代码示例中可以看到, 当我们使用传值参数时在方法中对引用类型 形参stu 修改时会影响 实参stu 的值,因为当形参是引用类型的时候,我们把实参传递过去的时候在内存中其实是开辟一个新的空间,把实参对象在堆中的内存地址拷贝过去了,因为两个地址中存的是对象在堆中存的相同地址,所以当修改 形参stu 的值会影响 实参stu 的值。
4.引用参数→值参数
图片解释:(来自刘铁猛C#入门视频)
代码示例:
static void Main(string[] args)
{
Student stu=new Student();
int x=100;
stu.Add(ref x);
Console.WriteLine(x);//打印 101
}
class Student
{
public void Add(ref int x)
{
x = x + 1;
Console.WriteLine(x);//打印 101
}
}
打印预览:
从代码示例中可以看到,当我们使用引用参数时在方法中对值类型 形参x 增加时,会影响到实参x,因为在传递引用参数→值类型的时候实参和形参指向内存中同一个地址,当我们对形参进行修改实参也会跟着改变。
5.引用参数→引用类型,并且创建新对象
图片解释:(来自刘铁猛C#入门视频)
代码示例:
static void Main(string[] args)
{
Student stu = new Student() { Name = "张三" };
//打印Name:李四,Hash:58225482
MetHodTest(ref stu);
//打印Name:李四,Hash:58225482
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
static void MetHodTest(ref Student stu)
{
stu = new Student() { Name = "李四" };
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
class Student
{
public string Name { get; set; }
}
打印预览:
从代码示例中可以看到, 当我们使用引用参数时在方法中对引用类型 形参stu 创建一个新对象时会影响 实参stu 的值,因为当形参是引用类型的时候,我们把实参传递过去的时候是把实参在内存中的地址传递给形参了,然后往形参上创建对象,创建的对象内存地址是保存在实参栈中内存空间,所以会影响实参。
6.引用参数→引用类型,不创建新对象只改变对象值
图片解释:(来自刘铁猛C#入门视频)
代码示例:
static void Main(string[] args)
{
Student stu = new Student() { Name = "张三" };
//打印Name:李四,Hash:58225482
MetHodTest(ref stu);
//打印Name:李四,Hash:58225482
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
static void MetHodTest(ref Student stu)
{
stu.Name = "李四";
Console.WriteLine($"Name:{stu.Name},Hash:{stu.GetHashCode()}");
}
class Student
{
public string Name { get; set; }
}
打印预览:
从代码示例中可以看到, 当我们使用引用参数时在方法中对引用类型 形参stu 修改对象值会影响 实参stu 的值,因为当形参是引用类型的时候,我们把实参传递过去的时候是把实参在内存中的地址传递给形参了,然后修改形参的对象,其实就是在修改实参上存的对象,所以会影响实参。
参考阅读
发表评论