C#如果数组是通过引用传递的,为什么参数数组必须通过修饰符ref传递?

C#如果数组是通过引用传递的,为什么参数数组必须通过修饰符ref传递?,c#,arrays,function,ref,modifier,C#,Arrays,Function,Ref,Modifier,我不明白为什么这个函数是这样写的: System.Array.Resize(ref int[],int) 如果默认情况下数组是通过引用传递的 为什么不是这样写的: System.Array.Resize(int[],int) 这是因为当我们将变量写入引用类型对象时,有两个部分,即实际的对象实例和变量名称所表示的引用(内部32位或64位内存地址指针,取决于平台)。你可以清楚地看到这一点 调用方法时,会复制此指针,但不会复制实例,因此: var a = new Blah {Prop = "1"};

我不明白为什么这个函数是这样写的:

System.Array.Resize(ref int[],int)
如果默认情况下数组是通过引用传递的 为什么不是这样写的:

System.Array.Resize(int[],int)

这是因为当我们将变量写入引用类型对象时,有两个部分,即实际的对象实例和变量名称所表示的引用(内部32位或64位内存地址指针,取决于平台)。你可以清楚地看到这一点

调用方法时,会复制此指针,但不会复制实例,因此:

var a = new Blah {Prop = "1"}; // Blah is a class, a reference type
Method(a);

void Method(Blah blah)
{
    blah.Prop = "2"; // changes the shared instance, we know this.

    blah = new Blah {Prop = "3"}; // has no effect.
}

Console.WriteLine(a.Prop); // 2
您可以看到,当我们在方法内部设置
blah
时,我们是在改变本地引用,而不是共享引用。现在,如果我们使用
ref
关键字:

var a = new Blah {Prop = "1"};
Method(ref a);

void Method(ref Blah blah)
{
    blah.Prop = "2"; // changes the shared instance, we know this.

    blah = new Blah {Prop = "3"}; // now changes ref a outside
}

Console.WriteLine(a.Prop); // 3!

因为参数
blah
是通过引用传递的,所以当我们对它进行变异时,我们会变异原始引用
a

数组确实是引用类型,这意味着对方法中传入的数组对象所做的更改将反映在调用方:

public static void Foo(int[] a) {
    a[0] = 1;
}

// ...
int[] a = new int[1];
Foo(a);
Console.WriteLine(a[0]); // 1
但是,如果将数组设置为方法中的其他内容:

public static void Foo(int[] a) {
    a = null;
}

// ...
int[] a = new int[1];
Foo(a);
Console.WriteLine(a[0]); // will not throw NRE
将参数声明为
ref
将允许重新分配参数,以反映调用方的情况


更改数组的大小需要创建一个新数组,然后重新分配参数。不能通过某种方式改变现有数组对象来调整数组大小。这就是为什么需要将其声明为
ref

的原因,简单地说,如果将数组作为
ref
参数传递给方法,则可以将其作为一个整体替换为在该方法中创建的另一个数组。 如果传递的数组没有
ref
关键字,则情况并非如此。 下面的代码说明了区别。 请注意,在这两种情况下都可以替换数组参数的单个元素(使用of而不使用
ref
关键字)

}

代码的输出如下所示(请注意,ByRef方法代码替换了数组

在调用NoRef之前:

1,3,4,7,9

在调用NoRef之后:

1,3,4,7,9

在调用ByRef之前:

1,3,4,7,9

在调用ByRef之后:


2、4、8、10都不是。数组是引用类型,通过引用传递是不同的。这是否回答了您的问题?如果Resize方法成功,则变量将指向不同的数组-已调整大小的数组。这是因为使用ref参数,您将传递对数组引用的引用,以便在方法体中可以修改数组引用本身。对于常规参数,这是不可能的-对数组的引用是通过复制传递的,因此即使在方法体中修改它,也将对复制的引用而不是原始引用进行操作。另请参见:
class Program
{
    static void PrintArr(string comment, int[] arr)
    {
        Console.WriteLine($"{comment}:");
        Console.WriteLine(string.Join(", ", arr.Select(e => e.ToString())));
    }
    static void NoRef(int[] arr)
    {
        int[] localArr = { 2, 4, 8, 10 };
        arr = localArr;
    }
    static void ByRef(ref int[] arr)
    {
        int[] localArr = { 2, 4, 8, 10 };
        arr = localArr;
    }

    static void Main()
    {
        int[] arr;
        arr = new int[] { 1, 3, 4, 7, 9 };

        PrintArr("Before NoRef is called", arr);
        NoRef(arr);
        PrintArr("After NoRef is called", arr);

        PrintArr("Before ByRef is called", arr);
        ByRef(ref arr);
        PrintArr("After ByRef is called", arr);

        Console.ReadLine();
    }
}