按值和按引用传递数组
本文关键字:数组 按引用传递 | 更新日期: 2023-09-27 18:32:20
这些是我正在阅读的 c# 书中的示例,只是在理解此示例的实际作用时遇到了一点麻烦,希望得到解释以帮助我进一步了解这里发生的事情。
//creates and initialzes firstArray
int[] firstArray = { 1, 2, 3 };
//Copy the reference in variable firstArray and assign it to firstarraycopy
int[] firstArrayCopy = firstArray;
Console.WriteLine("Test passing firstArray reference by value");
Console.Write("'nContents of firstArray " +
"Before calling FirstDouble:'n't");
//display contents of firstArray with forloop using counter
for (int i = 0; i < firstArray.Length; i++)
Console.Write("{0} ", firstArray[i]);
//pass variable firstArray by value to FirstDouble
FirstDouble(firstArray);
Console.Write("'n'nContents of firstArray after " +
"calling FirstDouble'n't");
//display contents of firstArray
for (int i = 0; i < firstArray.Length; i++)
Console.Write("{0} ", firstArray[i]);
// test whether reference was changed by FirstDouble
if (firstArray == firstArrayCopy)
Console.WriteLine(
"'n'nThe references refer to the same array");
else
Console.WriteLine(
"'n'nThe references refer to different arrays");
//method firstdouble with a parameter array
public static void FirstDouble(int[] array)
{
//double each elements value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] { 11, 12, 13 };
基本上有我想知道的代码是,这本书说如果数组是按值传递的,那么原始调用者不会被方法修改(据我所知)。因此,在方法 FirstDouble 结束时,他们尝试将局部变量数组分配给一组新的元素,该元素失败,并且显示时原始调用方的新值为 2,4,6。
现在我的困惑是方法 FirstDouble 中的 for 循环是如何将原始调用方 firstArray 修改为 2,4,6 如果它是按值传递的。我认为该值应保持为 1,2,3。
提前致谢
理解这一点的关键是了解值类型和引用类型之间的区别。
例如,考虑一个典型的值类型,int
。
int a = 1;
int b = a;
a++;
执行此代码后,a
的值为 2,b
的值为 1
。由于int
是值类型,因此b = a
获取a
值的副本。
现在考虑一个类:
MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;
由于类是引用类型,因此b = a
仅分配引用而不是值。因此,b
和a
都指同一个对象。因此,在a.MyProperty = 2
执行后,b.MyProperty == 2
自a
和b
引用同一对象。
考虑到您问题中的代码,数组是引用类型,因此对于此函数:
public static void FirstDouble(int[] array)
变量 array
实际上是一个引用,因为int[]
是一个引用类型。因此array
是按值传递的引用。
因此,对函数内部array
所做的修改实际上应用于array
引用的int[]
对象。因此,这些修改对于引用同一对象的所有引用都是可见的。这包括调用方持有的引用。
现在,如果我们看一下这个函数的实现:
public static void FirstDouble(int[] array)
{
//double each elements value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] { 11, 12, 13 };
}
还有一个并发症。for
循环只是将传递给函数的int[]
的每个元素加倍。这是调用方看到的修改。第二部分是将新的int[]
对象分配给局部变量array
。这对调用方是不可见的,因为它所做的只是更改引用array
的目标。由于引用array
是按值传递的,因此调用方看不到该新对象。
如果函数是这样声明的:
public static void FirstDouble(ref int[] array)
然后,引用array
将通过引用传递,并且调用者将在函数返回时看到新创建的对象{ 11, 12, 13 }
。
多么令人困惑的术语使用!
澄清一下,
-
对于方法
foo(int[] myArray)
,"按值传递引用(对象)"实际上意味着"传递对象地址(引用)的副本"。这个"副本"的值,即。myArray
,最初是原始对象的地址(引用),这意味着它指向原始对象。因此,对myArray
指向的内容的任何更改都会影响原始对象的内容。但是,由于
myArray
本身的"值"是一个副本,因此对该"值"的任何更改都不会影响原始对象或其内容。 -
对于方法
foo(ref int[] refArray)
,"通过引用传递引用(对象)"意味着"传递对象的地址(引用)本身(而不是副本)"。这意味着refArray
实际上是对象本身的原始地址,而不是副本。因此,对refArray
的"值"或refArray
所指向的内容的任何更改都是对原始对象本身的直接更改。
所有方法参数都是按值传递的,除非您特别看到ref
或out
。
数组是引用类型。 这意味着您正在按值传递引用。
引用本身仅在为其分配新数组时更改,这就是这些赋值不会反映在调用方中的原因。 当您取消引用对象(此处的数组)并修改基础值时,您不会更改变量,只是更改它指向的内容。 这种变化也会被调用者"看到",即使变量(即它指向的内容)保持不变。
了解.NET开源以实现逻辑的想法;
//Sample Code, Illustration;
Method1(params dynamic[] var1) {
var1[0]=new dynamic[3] { 1,2,3 }
}
VaR1 未指定或不能引用 ?使用场景将是...
//Sample Code, Illustration;
dynamic[] test = new dynamic[];
Method1( ref test,x,x,x,x );
System.Windows.MessageBox.Show( test[2].ToString() );
仅在以下情况下指示 ref,而不是特定于参数;以及对数组项目的引用;
//result is IndexOutOfBounds;
这只是一个插图,可以通过返回数组并使用如下方式来完成:
test = Method1( test,... );
而不是:
Method1( ref test,x,x,..., ref test[x], ref test2, ... );