这些是来自ac#book的例子,我正在阅读这个例子实际上正在做的一点点麻烦,想要一个解释来帮助我进一步了解这里发生的事情.
//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 };
Run Code Online (Sandbox Code Playgroud)
基本上有代码我想知道的是,本书说的是数组是否通过值传递,而不是原始调用者没有被方法修改(根据我的理解).因此,在方法FirstDouble结束时,他们尝试将局部变量数组分配给一组失败的新元素,并且显示原始调用者的新值为2,4,6.
现在我的困惑是如何通过值传递方法FirstDouble中的for循环如何将原始调用者firstArray修改为2,4,6.我认为价值应该保持在1,2,3.
提前致谢
Dav*_*nan 37
理解这一点的关键是要知道值类型和引用类型之间的区别.
例如,考虑典型的值类型int.
int a = 1;
int b = a;
a++;
Run Code Online (Sandbox Code Playgroud)
执行此代码后,a其值为2,并b具有该值1.因为int是值类型,所以b = a取值的副本a.
现在考虑一个类:
MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;
Run Code Online (Sandbox Code Playgroud)
因为类是引用类型,所以b = a只分配引用而不是值.所以b,a两者都指向同一个对象.因此,在a.MyProperty = 2执行之后,b.MyProperty == 2因为a并且b引用相同的对象.
考虑到你的问题中的代码,数组是一个引用类型,因此对于这个函数:
public static void FirstDouble(int[] array)
Run Code Online (Sandbox Code Playgroud)
变量array实际上是一个引用,因为它int[]是一个引用类型.所以array是一个基准是按值传递.
因此,array对函数内部所做的修改实际上应用于int[]所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 };
}
Run Code Online (Sandbox Code Playgroud)
还有一个复杂因素.该for循环简单加倍的每个元素int[]传递给函数.这是调用者看到的修改.第二部分是将新int[]对象赋值给局部变量array.这对调用者是不可见的,因为它只是改变了引用的目标array.并且由于引用array是按值传递的,因此调用者不会看到该新对象.
如果函数声明如下:
public static void FirstDouble(ref int[] array)
Run Code Online (Sandbox Code Playgroud)
然后引用array将通过引用传递,并且调用程序将{ 11, 12, 13 }在函数返回时看到新创建的对象.
除非您特别看到ref或 ,否则所有方法参数都是按值传递的out。
数组是引用类型。这意味着您正在按值传递引用。
引用本身仅在您为其分配新数组时才会更改,这就是为什么这些分配不会反映在调用者中的原因。当您取消引用对象(此处为数组)并修改基础值时,您不会更改变量,只是它指向的内容。这种变化也会被调用者“看到”,即使变量(即它指向的)保持不变。
小智 7
多么令人困惑的用语!
澄清,
1)对于方法foo(int [] myArray),"按值传递引用(对象)"实际上意味着"传递对象地址(引用)的副本".这个'副本'的价值,即.myArray,最初是原始对象的Address(引用),意味着它指向原始对象.因此,myArray指向的内容的任何更改都将影响原始对象的内容.
但是,由于myArray本身的'value'是一个副本,因此对该'value'的任何更改都不会影响原始对象及其内容.
2)对于方法foo(ref int [] refArray),"通过引用传递引用(对象)"意味着"传递对象的地址(引用)本身(不是副本)".这意味着refArray实际上是对象本身的原始地址,而不是副本.因此,对refArray的'value'或refArray指向的内容的任何更改都是对原始对象本身的直接更改.
| 归档时间: |
|
| 查看次数: |
49365 次 |
| 最近记录: |