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();
}
}