byref 与 byval,变量与数组

by ref vs. by val, variable vs. array

可变值:

static void Main(string[] args)
{
    int i = 3;
    method1(i);
    Console.WriteLine(i);
    Console.ReadLine();
}
static void method1(int z)
{
    z *= 2;
}

输出为 3,因为 method1 没有更改 Main 中的变量。

参考变量:

static void Main(string[] args)
{
    int i = 3;
    method1(ref i);
    Console.WriteLine(i);
    Console.ReadLine();
}
static void method1(ref int z)
{
    z *= 2;
}

输出为 6,因为 method1 更改了 Main 中的变量。

按值排列:

class Program
{
    static void Main(string[] args)
    {
        int[] i = { 13, 1, 5 };
        method1(i);
        Console.WriteLine(String.Join(",",i));
        Console.ReadLine();
    }
    static void method1(int[] z)
    {
        for(int m=0; m<z.Length;m++)
        {
            z[m] *= 2;
        }
    }
}

输出为 26、2、10。

数组参考:

class Program
{
    static void Main(string[] args)
    {
        int[] i = { 13, 1, 5 };
        method1(ref i);
        Console.WriteLine(String.Join(",",i));
        Console.ReadLine();
    }
    static void method1(ref int[] z)
    {
        for(int m=0; m<z.Length;m++)
        {
            z[m] *= 2;
        }
    }
}

输出又是 26、2、10。

结论: 变量可以按值或按引用传递, 与只能通过引用传递的数组相反。 这是正确的吗? 如果不是——method1(ref int[] z) 和 method1(int[] z) 有什么区别?我们预计什么时候会得到不同的结果?

当引用类型对象按值传递时,对对象的引用实际上按值传递,因此如果您在方法实现中更新对新对象的引用,引用将开始指向新的内存地址。

您可以通过稍微修改方法实现来查看结果的差异,以便将即将到来的输入数组初始化为新实例,例如:

static void method1(int[] z)
{
   z = new int[3]; // new instance created and z has reference to it
                   // while calling side still refers to old memory location
                   // which is { 13, 1, 5 }
   for(int m=0; m<z.Length;m++)
   {
        z[m] *= 2;
    }
}

现在,当您调用按值传递方法时,它将仅在本地为此方法修改 z 并且外部数组不会受到影响,而如果您通过引用传递它,那么两个数组都会受到影响变化。

发生的事情是我们通过创建一个新的数组实例将数组 z 设置为引用新的内存位置,因此方法中的引用被更新为指向新的内存位置,但调用方引用仍然指向在调用方法之前实例化的旧数组。

当您通过引用传递时,两个变量都将更新以指向新的内存位置。

static void method1(ref int[] z)
{
   z = new int[3]; // new instance created and z has reference to it
                   // now calling side also refers to new memory location
                   // which is new int[3];
   for(int m=0; m<z.Length;m++)
   {
        z[m] *= 2;
    }
}