c#引用传递和值传递

来源:互联网 发布:农行网银支持mac吗 编辑:程序博客网 时间:2024/05/24 02:37

    我们知道,c#的数据类型分为值类型和引用类型。值类型包括基本类型(数值类型,bool类型等)、结构和枚举,引用类型包括类、委托、数组等。在使用方法传递变量时,就需要了解值类型和引用类型作为参数传递的机制了。

    先看下面一段代码:

     

    输出结果为:

    10

    10

    10

    1010

    通过结果发现,值类型aNumber在经过函数处理后,再次输出时值并没有发生变化,而引用类型class A的属性发生了变化,为什么会发生这种情况?

    数据类型在内存中的保存时,值类型保存在堆栈中,引用类型将它的值保存在托管堆中,在堆栈中保存的是对堆上地址的引用,在方法中传递参数时,所有类型都是传递堆栈中的位置,具体过程为先在堆栈上复制一个传递的对象,然后将该对象传给参数,所以显而易见,数值类型保存在堆栈中,作为参数传递时直接复制了数值的一个副本给方法,方法对该副本所做的任何操作都不会影响到该数值的原值,但是引用类型复制的是堆栈上对堆的引用,该引用指向的仍然是堆上的引用类型,所以对应用类型所做的操作都会引起其本身的改变。

    下面我们再看一段代码:

     

    输出结果为:

    10

    10

    string类型是引用类型,所以在方法中传递的仍然是堆栈中对string变量引用的副本,但是为什么上面的代码并没有改变string变量的值呢?这里我们就需要知道,在c#中,string是一个比较特殊的类型,微软并不提倡我们些如下的代码:

     

    上面的代码首先声明了一个变量aStr,然后将其与另一个字符串连接,在具体实现过程中,系统先在托管对中保存了aaaaa值,在进行连接运算时,先将aaaaa的值复制一份,然后在后面连接bbbbb,最后将得到的新值的地址赋给aStr,所以此时aaaaa并没有在内存中删除,直到垃圾回收器将其回收。比较好的做法是在需要进行连接字符串操作时,使用StringBulider类进行操作,它会直接在对象后面进行连接操作,而不会先将值复制一遍。

    回到上面的方法来,当String类型作为参数传递时,系统会先在托管堆中将值复制一遍,堆栈上得到的地址指向这个新值,所以方法对string类型的操作并不影响到它的原有值。

    这里我们必然会想到,如果我需要使用一个方法改变值类型的值咋办呢?比如说,当我们需要一个方法输出多个值时,我们知道,当方法有返回值时,最后return回来的总是只有一个值,如果我需要将参数a、b同时传入方法并得到两个结果时,怎么办呢?此时就需要使用引用传递了。c#的方法使用了ref关键字,该关键字表示将参数作为引用类型传递,看下面的代码:

     

    输出结果:

    10

    50

    20

    100

    通过这个方法,我们同时改变了a和b的值。

 

原创粉丝点击