C#中的引用传递、值传递

来源:互联网 发布:尔雅网络通识课 编辑:程序博客网 时间:2024/05/18 17:03

 先来说下C#中的数据类型.分值类型和引用类型两大类.

  值类型:直接存储数据的值,保存在内存中

  引用类型:存储对值的引用,实际上存储的就是一个内存的地址

  C#预定义的简单类型,像int,float,bool,char都是值类型,另外enum(枚举),struct(结构)也是值类型

  string,数组,自定义的class类、接口、委托和封装就都是引用类型了.其中的string是比较特殊的引用类型

  C#函数的参数如果不加ref,out这样的修饰符显式申明参数是通过引用传递外,默认都是值传递.

 

 

一、传递参数

  既可以通过值也可以通过引用传递参数。通过引用传递参数允许函数成员(方法、属性、索引器、运算符和构造函数)更改参数的值,并保持该更改。

二、传递值类型参数

   值类型变量直接包含其数据,这与引用类型变量不同,后者包含对其数据的引用。因此,向方法传递值类型变量意味着向方法传递变量的一个副本。方法内发生的对参数的更改对该变量中存储的原始数据无任何影响。如果希望所调用的方法更改参数的值,必须使用 ref 或 out 关键字通过引用传递该参数。为了简单起见,下面的示例使用 ref

  1. 通过值传递值类型:

复制代码
代码class PassingValByVal{    static void SquareIt(int x)    {        x *= x;        System.Console.WriteLine("The value inside the method: {0}", x);  //25    }    static void Main()    {        int n = 5;        System.Console.WriteLine("The value before calling the method: {0}", n);  //5        SquareIt(n);         System.Console.WriteLine("The value after calling the method: {0}", n);  //5    }}
复制代码
变量 n 为值类型,包含其数据(值为 5)。当调用 SquareIt 时,n 的内容被复制到参数 x 中,在方法内将该参数求平方。但在 Main 中,n 的值在调用 SquareIt 方法前后是相同的。实际上,方法内发生的更改只影响局部变量 x

2.通过引用传递值类型

下面的示例除使用 ref 关键字传递参数以外,其余与上一示例相同。参数的值在调用方法后发生更改

复制代码
代码class PassingValByRef{    static void SquareIt(ref int x)    {        x *= x;        System.Console.WriteLine("The value inside the method: {0}", x);//25    }    static void Main()    {        int n = 5;        System.Console.WriteLine("The value before calling the method: {0}", n);//5        SquareIt(ref n);         System.Console.WriteLine("The value after calling the method: {0}", n);//25    }}
复制代码

本示例中,传递的不是 n 的值,而是对 n 的引用。参数 x 不是 int 类型,它是对 int 的引用(本例中为对 n 的引用)。因此,当在方法内对 x 求平方时,实际被求平方的是 x 所引用的项:n

三、传递引用类型参数

  引用类型的变量不直接包含其数据;它包含的是对其数据的引用。当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值。但是无法更改引用本身的值;也就是说,不能使用相同的引用为新类分配内存并使之在块外保持。若要这样做,应使用 ref 或 out 关键字传递参数。为了简单起见,下面的示例使用 ref

  1. 通过值传递引用类型

下面的示例演示通过值向 Change 方法传递引用类型的参数 arr。由于该参数是对 arr 的引用,所以有可能更改数组元素的值。但是,试图将参数重新分配到不同的内存位置时,该操作仅在方法内有效,并不影响原始变量 arr
复制代码
代码class PassingRefByVal {    static void Change(int[] pArray)    {        pArray[0] = 888;         pArray = new int[5] {-3, -1, -2, -3, -4};        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);//-3    }    static void Main()     {        int[] arr = {1, 4, 5};        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr [0]);//1        Change(arr);        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);//888    }}
复制代码
在上个示例中,数组 arr 为引用类型,在未使用 ref 参数的情况下传递给方法。在此情况下,将向方法传递指向 arr 的引用的一个副本。输出显示方法有可能更改数组元素的内容,在这种情况下,从 1改为 888。但是,在 Change 方法内使用 new 运算符来分配新的内存部分,将使变量 pArray 引用新的数组。因此,这之后的任何更改都不会影响原始数组 arr(它是在 Main 内创建的)。实际上,本示例中创建了两个数组,一个在 Main 内,一个在 Change 方法内。

  2. 通过引用传递引用类型

本示例除在方法头和调用中使用 ref 关键字以外,其余与上个示例相同。方法内发生的任何更改都会影响调用程序中的原始变量
复制代码
class PassingRefByRef {    static void Change(ref int[] pArray)    {        pArray[0] = 888;        pArray = new int[5] {-3, -1, -2, -3, -4};        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);//-3    }            static void Main()     {        int[] arr = {1, 4, 5};        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[0]);//1        Change(ref arr);        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]);//-3    }}
复制代码
方法内发生的所有更改都影响 Main 中的原始数组。实际上,使用 new 运算符对原始数组进行了重新分配。因此,调用 Change 方法后,对 arr 的任何引用都将指向 Change 方法中创建的五个元素的数组。
0 0
原创粉丝点击