引用参数:方法声明时,使用ref修饰符修饰的形参称为引用参数。
- 引用参数与值参数不同,引用参数不创建副本,直接使用实参传过来的数据
- 调用有引用参数的方法时,需要在实参前加上ref关键字
- 由于引用参数直接使用实参所指向的数据的位置,所以调用方法前实参必须被明确赋值
声明带引用参数的方法,并且引用参数为值类型
static void Main(string[] args)
{
int x;
x = 10;
AddOne(ref x);
Console.WriteLine("调用方法后"+x);//11
Console.Read();
}
static void AddOne(ref int p)
{
p = p + 1;
Console.WriteLine(p);//11
}
分析:由于引用参数p不会创建副本,所以局部变量p其实直接操作的就是x指向的存储位置;所以如果我们在调用方法前 不对实参进行初始化或者赋值,他们就无法找到自己表示哪一个内存地址的值
声明带引用参数的方法,并且引用参数为引用类型,在方法内部,为引用参数赋了一个新值
class Program
{
static void Main(string[] args)
{
Student stu;
//在调用方法前,必须对将要作为引用参数的实参stu显示赋值
stu = new Student() { Name = "xiaoming", Age = 18 };
Console.WriteLine("调用前:"+stu.GetHashCode());//调用前:46104728
PrintInfo(ref stu);
Console.WriteLine(stu.Name + "--" + stu.Age);//jaychou--33
Console.WriteLine("调用后:"+stu.GetHashCode());//调用后:12289376
Console.Read();
}
static void PrintInfo(ref Student student)
{
student = new Student() { Name = "jaychou", Age = 33 };
Console.WriteLine(student.GetHashCode());//12289376
Console.WriteLine(student.Name + "--" + student.Age);//jaychou--33
}
}
class Student
{
public int Age { get; set; }
public string Name { get; set; }
}
分析:这里student作为引用参数,student不再创建副本,所以操作student就是在操作实参stu;当student被新对对象赋值,那么就相当于stu也被指向新对象
小技巧:如果对于副本什么的不理解,不妨将引用变量当成实参的别名吧,在调用前后并未增加新的内存空间。
声明引用参数,并且参数类型是引用类型,在调用方法中未创建新的对象赋值给形参,只操作对象的属性。
class Program
{
static void Main(string[] args)
{
Student stu;
//在调用方法前,必须对将要作为引用参数的实参stu显示赋值
stu = new Student() { Name = "xiaoming", Age = 18 };
Console.WriteLine("调用前:" + stu.GetHashCode());//调用前:45653674
PrintInfo(ref stu);
Console.WriteLine(stu.Name + "--" + stu.Age);//周周--18
Console.WriteLine("调用后:" + stu.GetHashCode());//调用后:45653674
Console.Read();
}
static void PrintInfo(ref Student student)
{
student.Name = "周周";
Console.WriteLine(student.GetHashCode());//45653674
Console.WriteLine(student.Name + "--" + student.Age);//周周--18
}
}
class Student
{
public int Age { get; set; }
public string Name { get; set; }
}
说明:虽然这种操作方式和值参数--类型为引用类型的输出效果一致,但是在内存中两者是不同的。
使用ref参数注意好先赋值后调用就好,以上便是对ref参数的总结,记录下来,以便以后查阅。