ref关键字理解(c#)
今天认真研究了ref关键字用法,写下我对ref关键字用法的自我理解. 从两方面分析ref用法:值类型的引用传递和引用类型的引用传递
值类型的引用传递:
代码如下(1):
class Program
{
static void Main(string[] args)
{
int _num = 1;
ChangeNum(_num);
Console.WriteLine("num:{0}", _num);//输出: num:1
Console.ReadKey();
}
public static void ChangeNum(int num)
{
num = 12;
}
}
(1)代码理解:这段代码理解->值类型是存储在栈中的,当函数传递值类型中时,函数中传递值类型变量时,会在栈中再copy一份栈数据,即栈地址不同但是值相同.所以函数中改变
变量的值只是改变新生成的栈地址中的值,而函数外的变量即原先栈地址中的值不变,所以(1)代码会输出1而不是12.
运用ref,值类型引用传递,代码如下(2):
class Program
{
static void Main(string[] args)
{
int _num = 1;
ChangeNum(ref _num);
Console.WriteLine("num:{0}", _num);//输出: num:12
Console.ReadKey();
}
public static void ChangeNum(ref int num)
{
num = 12;
}
}
(2)代码理解:上面代码运用了ref关键字即值类型的引用传递,值类型运用ref在函数中传递变量时,同样会在栈中生成一份地址不同的数据,只不过栈中的地址不是原先变量的值1而是原先变量在栈中的地址.所以栈中的数据只有一份,函数中改变变量值即改变栈地址所对应栈中的值,类似引用类型,不过此时地址不是指向堆而是栈,所以会输出12
引用类型的引用传递:
代码如下(3) :
class Program
{
static void Main(string[] args)
{
Product _pro = new Product("故事会", 1);
ChangePrice(ref _pro);
Console.ReadKey();
}
public static void ChangePrice(ref Product pro)
{
pro.Price = 12;
//pro = null;
Console.WriteLine("Product->Price:{0}",pro.Price);
}
}
public class Product
{
public Product(string name, int price)
{
this.Name = name;
this.Price = price;
}
public string Name { get; set; }
public int Price { get; set; }
}
很多人认为引用类型,用与不用没有ref没有什么区别,其实如果上面代码(3)ChangePrice中//pro = null;注释去掉,会发现有所不同.因为不用ref传递引用类型时函数传递应用类型变量时是在栈中又生成一份数据,里面值与传递变量在栈中的值一样,即指向同一个堆地址.如果在不用ref时添加pro = null代码,会报错即只不过把传递变量时生成的栈中指向堆的地址清空置为null,此时Console.WriteLine("Product->Price:{0}",pro.Price);中pro就不存在了. 但是原先的栈变量不变.如果用ref时,添加pro = null代码,也会报错,因为函数传递引用变量时,在栈中又生成一份栈地址,不过栈中地址值是原先栈的地址
总结:引用传递时又赋值一份栈内存,只不过栈中的值存的是被赋值栈的地址