手记

C#编程引用类型和值类型 以及引用传递和值传递

我们从最简单的说起(基础知识,懂的同学直接往下拉),直接上代码:

static int amount;
static void AddTV(int amount)
{
    amount++;
    Console.WriteLine("方法中,amount="+amount);
}

然后,我们将参数amout传入AddTV()方法,希望能让其+1

amount = 10;
AddTV(amount);
Console.WriteLine("AddTV(amount)执行之后,amount=" + amount);

 那么执行的结果呢?

amount的数量并没有发生变化。

为什么没有变呢?

这是最入门的知识,通常的解释是:

amount是int类型,int是值类型,所以当它作为参数时,传递给方法的是它的一个副本(复制品),因此方法中改变的是它的副本的值,amount本身并没有改变。

ref 关键字,如下所示:

static void AddTV(ref int amount)
{
    amount++;
    Console.WriteLine("方法中,amount="+amount);
}

大家自己跑一下,看看结果有什么不一样。

这叫做参数的引用传递。

 

这是最基础的知识,非常清晰。好的,接着,C#是面向对象的语言嘛,我们要引入一个对象。

public class House
{
    public int TVAmount { get; set; }
}

然后,我们把House对象作为参数传递,值传递,不带ref的。如下所示:

static void AddTV(House house)
{
    house.TVAmount++;
    Console.WriteLine("方法中,house.TVAmount=" + house.TVAmount);
}
 
 
    House house = new House();
    AddTV(house);
    Console.WriteLine("AddTV(house)执行之后,house.TVAmount=" + house.TVAmount);

执行之后你会发现:

咦?house.TVAmount的值变了耶!

为什么呢?

有的同学听到的解释是这样的:

House是对象,是引用类型,引用类型作为参数传递到方法中,它的值会被方法改变。

 

值类型传进去不变,引用类型传进去要变,但值类型引用传递又要变……虽然有点绕,但死背下来也行。

讲课这些天(五)怎么才能把代码写好?)

值类型的引用传递,和引用类型的值传递,效果都一样,那他们有什么区别呢?

 

Good question!

实际上,死背上面的,是会出问题的,我还是用代码展示一下:

static void AddTV(House house)
{
    house = new House();
    house.TVAmount++;
    Console.WriteLine("方法中,house.TVAmount=" + house.TVAmount);
}


这样写,眼尖的同学一眼就能看出差别:这一次方法体内多了一个:house = new House();

不要以为这是抽风啊,实际的开发代码中,各种各样的原因,很多时候都确实会在方法体内重新new一个参数实例的。

那运行结果怎么样的呢?

怎么样?!引用类型也不好使了?


不像JavaScript到处都是bug和设计缺陷(是的,日常黑js一百年,),C#是一门严谨清晰的语言,不会有什么“灵异”事件。现象和你的想法不一致,一定是你的想法出了问题。

所以,要真正地弄明白这里面的道道,我们还是要回到原点:

 

首先的首先,看看这代码,你真的明白是什么意思么:

House house
    =
    new House();

我为什么要写成三行?

因为这其实是三个过程:

  • House house 这是声明了一个变量

  • new House() 这是生成了一个对象

  • = 把 house 和 new House() 关联起来

注意,注意我用的是“关联”,很多人喜欢说“赋值”,甚至“等于”,这就容易造成我们理解上的误区。

house和New House,是不同的数据储存。事实上,在house里面,有一个记录了new Houuse()存储位置的“引用”(reference,这个英文单词有助于我们理解)。所以,当我们house.TVAmount的时候,是通过house找到new House(),然后得到new House()的数据进行操作。

不知道大家能不能明白这一点?

整个这一块都是int i,int i 里面就直接的存储了10这个数据,没有引用,int i里直接存放数值10,所以叫做“值类型”。

 

好了,理解了上面的概念之后,我们回头来看方法参数。

C#的说法非常的清晰,只看有没有 ref 关键字:

  1. 不带ref的,一定是“值传递”

  2. 带ref的,一定是“引用传递”

和传递的是什么类型的参数,半毛钱关系没有。

关键是,你要知道:当参数为引用类型时,传递的不是对象(new House()),而是对象的引用(house)

所以,

  • 如果是值传递,传递的是 对象引用的 副本

  • 如果是引用传递,传递的是 对象引用 本身

0人推荐
随时随地看视频
慕课网APP