These are example from a c# book that I am reading just having a little trouble grasping what this example is actually doing would like an explanation to help me further understand what is happening here.
这些是我正在阅读的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 };
Basically there is the code what I would like to know is that the book is saying if the array is passed by value than the original caller does not get modified by the method(from what i understand). So towards the end of method FirstDouble they try and assign local variable array to a new set of elements which fails and the new values of the original caller when displayed are 2,4,6.
基本上,我想知道的是,如果数组是按值传递的,那么原始调用者就不会被方法修改(据我所知)。所以在方法FirstDouble的结尾,他们尝试将局部变量数组分配给一组新的元素,这些元素失败了,当显示时原始调用者的新值是2,4,6。
Now my confusion is how did the for loop in method FirstDouble modify the original caller firstArray to 2,4,6 if it was passed by value. I thought the value should remain 1,2,3.
现在我的困惑是,FirstDouble方法中的for循环如何将原始调用者firstArray修改为2,4,6,如果它是通过值传递的。我认为值应该是1 2 3。
Thanks in advance
谢谢提前
3 个解决方案
#1
33
The key to understanding this is to know the difference between a value type and a reference type.
理解这一点的关键是要知道值类型和引用类型之间的区别。
For example, consider a typical value type, int
.
例如,考虑一个典型的值类型int。
int a = 1;
int b = a;
a++;
After this code has executed, a
has the value 2, and b
has the value 1
. Because int
is a value type, b = a
takes a copy of the value of a
.
执行此代码后,a的值为2,b的值为1。因为int是一个值类型,b = a取a的值的副本。
Now consider a class:
现在考虑一个类:
MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;
Because classes are reference types, b = a
merely assigns the reference rather than the value. So b
and a
both refer to the same object. Hence, after a.MyProperty = 2
executes, b.MyProperty == 2
since a
and b
refer to the same object.
因为类是引用类型,所以b = a只分配引用而不是值。所以b和a都指向同一个物体。因此,后。执行MyProperty = 2, b。MyProperty == 2,因为a和b指的是同一个对象。
Considering the code in your question, an array is a reference type and so for this function:
考虑到您问题中的代码,数组是引用类型,因此对于这个函数:
public static void FirstDouble(int[] array)
the variable array
is actually a reference, because int[]
is a reference type. So array
is a reference that is passed by value.
变量数组实际上是一个引用,因为int[]是一个引用类型。数组是通过值传递的引用。
Thus, modifications made to array
inside the function are actually applied to the int[]
object to which array
refers. And so those modifications are visible to all references that refer to that same object. And that includes the reference that the caller holds.
因此,对函数中数组的修改实际上应用于数组引用的int[]对象。这些修改对于所有引用相同对象的引用都是可见的。这包括调用者持有的引用。
Now, if we look at the implementation of this function:
现在,如果我们看看这个函数的实现:
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 };
}
there is one further complication. The for
loop simply doubles each element of the int[]
that is passed to the function. That's the modification that the caller sees. The second part is the assignment of a new int[]
object to the local variable array
. This is not visible to the caller because all it does is to change the target of the reference array
. And since the reference array
is passed by value, the caller does not see that new object.
还有一个更复杂的问题。for循环只是将传递给函数的int[]的每个元素加倍。这就是调用者看到的修改。第二部分是向局部变量数组分配一个新的int[]对象。这对调用者不可见,因为它所做的就是更改引用数组的目标。由于引用数组是通过值传递的,所以调用者不会看到新的对象。
If the function had been declared like this:
如果函数是这样声明的:
public static void FirstDouble(ref int[] array)
then the reference array
would have been passed by reference and the caller would see the newly created object { 11, 12, 13 }
when the function returned.
然后引用数组将通过引用传递,当函数返回时,调用者将看到新创建的对象{11,12,13}。
#2
2
All method parameters are passed by value unless you specifically see ref
or out
.
所有方法参数都按值传递,除非您特别看到ref或out。
Arrays are reference types. This means that you're passing a reference by value.
数组是引用类型。这意味着您正在按值传递引用。
The reference itself is only changed when you assign a new array to it, which is why those assignments aren't reflected in the caller. When you de-reference the object (the array here) and modify the underlying value you aren't changing the variable, just what it points to. This change will be "seen" by the caller as well, even though the variable (i.e. what it points to) remains constant.
只有当您为引用分配一个新数组时,引用本身才会被更改,这就是为什么这些赋值没有在调用者中反映出来。当您对对象(这里的数组)进行反引用并修改底层值时,您并没有改变变量,只是改变它指向的内容。这个变化也会被调用者“看到”,即使变量(即它指向什么)保持不变。
#3
1
What a confusing use of terms!
多么令人困惑的使用术语!
To clarify,
澄清一下,
1) for a method foo(int[] myArray), "passing a reference (object) by value" actually means "passing a copy of the object's address (reference)". The value of this 'copy', ie. myArray, is initially the Address (reference) of the original object, meaning it points to the original object. Hence, any change to the content pointed to by myArray will affect the content of the original object.
1)对于foo(int[] myArray)方法,“通过值传递引用(对象)”实际上意味着“传递对象地址(引用)的副本”。这“复制品”的价值。myArray,最初是原始对象的地址(引用),意味着它指向原始对象。因此,myArray指向的内容的任何更改都会影响原始对象的内容。
However, since the 'value' of myArray itself is a copy, any change to this 'value' will not affect the original object nor its contents.
但是,由于myArray本身的“值”是一个副本,因此对这个“值”的任何更改都不会影响原始对象或其内容。
2) for a method foo(ref int[] refArray), "passing a reference (object) by reference" means "passing the object's address (reference) itself (not a copy)". That means refArray is actually the original address of the object itself, not a copy. Hence, any change to the 'value' of refArray, or the content pointed to by refArray is a direct change on the original object itself.
2)对于方法foo(ref int[] refArray),“通过引用传递引用(对象)”意味着“传递对象的地址(引用)本身(而不是副本)”。这意味着refArray实际上是对象本身的原始地址,而不是副本。因此,对refArray的“值”或refArray所指向的内容的任何更改都是对原始对象本身的直接更改。
#1
33
The key to understanding this is to know the difference between a value type and a reference type.
理解这一点的关键是要知道值类型和引用类型之间的区别。
For example, consider a typical value type, int
.
例如,考虑一个典型的值类型int。
int a = 1;
int b = a;
a++;
After this code has executed, a
has the value 2, and b
has the value 1
. Because int
is a value type, b = a
takes a copy of the value of a
.
执行此代码后,a的值为2,b的值为1。因为int是一个值类型,b = a取a的值的副本。
Now consider a class:
现在考虑一个类:
MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;
Because classes are reference types, b = a
merely assigns the reference rather than the value. So b
and a
both refer to the same object. Hence, after a.MyProperty = 2
executes, b.MyProperty == 2
since a
and b
refer to the same object.
因为类是引用类型,所以b = a只分配引用而不是值。所以b和a都指向同一个物体。因此,后。执行MyProperty = 2, b。MyProperty == 2,因为a和b指的是同一个对象。
Considering the code in your question, an array is a reference type and so for this function:
考虑到您问题中的代码,数组是引用类型,因此对于这个函数:
public static void FirstDouble(int[] array)
the variable array
is actually a reference, because int[]
is a reference type. So array
is a reference that is passed by value.
变量数组实际上是一个引用,因为int[]是一个引用类型。数组是通过值传递的引用。
Thus, modifications made to array
inside the function are actually applied to the int[]
object to which array
refers. And so those modifications are visible to all references that refer to that same object. And that includes the reference that the caller holds.
因此,对函数中数组的修改实际上应用于数组引用的int[]对象。这些修改对于所有引用相同对象的引用都是可见的。这包括调用者持有的引用。
Now, if we look at the implementation of this function:
现在,如果我们看看这个函数的实现:
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 };
}
there is one further complication. The for
loop simply doubles each element of the int[]
that is passed to the function. That's the modification that the caller sees. The second part is the assignment of a new int[]
object to the local variable array
. This is not visible to the caller because all it does is to change the target of the reference array
. And since the reference array
is passed by value, the caller does not see that new object.
还有一个更复杂的问题。for循环只是将传递给函数的int[]的每个元素加倍。这就是调用者看到的修改。第二部分是向局部变量数组分配一个新的int[]对象。这对调用者不可见,因为它所做的就是更改引用数组的目标。由于引用数组是通过值传递的,所以调用者不会看到新的对象。
If the function had been declared like this:
如果函数是这样声明的:
public static void FirstDouble(ref int[] array)
then the reference array
would have been passed by reference and the caller would see the newly created object { 11, 12, 13 }
when the function returned.
然后引用数组将通过引用传递,当函数返回时,调用者将看到新创建的对象{11,12,13}。
#2
2
All method parameters are passed by value unless you specifically see ref
or out
.
所有方法参数都按值传递,除非您特别看到ref或out。
Arrays are reference types. This means that you're passing a reference by value.
数组是引用类型。这意味着您正在按值传递引用。
The reference itself is only changed when you assign a new array to it, which is why those assignments aren't reflected in the caller. When you de-reference the object (the array here) and modify the underlying value you aren't changing the variable, just what it points to. This change will be "seen" by the caller as well, even though the variable (i.e. what it points to) remains constant.
只有当您为引用分配一个新数组时,引用本身才会被更改,这就是为什么这些赋值没有在调用者中反映出来。当您对对象(这里的数组)进行反引用并修改底层值时,您并没有改变变量,只是改变它指向的内容。这个变化也会被调用者“看到”,即使变量(即它指向什么)保持不变。
#3
1
What a confusing use of terms!
多么令人困惑的使用术语!
To clarify,
澄清一下,
1) for a method foo(int[] myArray), "passing a reference (object) by value" actually means "passing a copy of the object's address (reference)". The value of this 'copy', ie. myArray, is initially the Address (reference) of the original object, meaning it points to the original object. Hence, any change to the content pointed to by myArray will affect the content of the original object.
1)对于foo(int[] myArray)方法,“通过值传递引用(对象)”实际上意味着“传递对象地址(引用)的副本”。这“复制品”的价值。myArray,最初是原始对象的地址(引用),意味着它指向原始对象。因此,myArray指向的内容的任何更改都会影响原始对象的内容。
However, since the 'value' of myArray itself is a copy, any change to this 'value' will not affect the original object nor its contents.
但是,由于myArray本身的“值”是一个副本,因此对这个“值”的任何更改都不会影响原始对象或其内容。
2) for a method foo(ref int[] refArray), "passing a reference (object) by reference" means "passing the object's address (reference) itself (not a copy)". That means refArray is actually the original address of the object itself, not a copy. Hence, any change to the 'value' of refArray, or the content pointed to by refArray is a direct change on the original object itself.
2)对于方法foo(ref int[] refArray),“通过引用传递引用(对象)”意味着“传递对象的地址(引用)本身(而不是副本)”。这意味着refArray实际上是对象本身的原始地址,而不是副本。因此,对refArray的“值”或refArray所指向的内容的任何更改都是对原始对象本身的直接更改。