C# 按值和按引用传递数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10325323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing Arrays by Value and by Reference
提问by Tim
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.
这些是我正在阅读的 ac# 书中的示例,只是在理解此示例实际执行的操作时遇到了一些麻烦,希望得到解释以帮助我进一步了解此处发生的情况。
//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
提前致谢
采纳答案by David Heffernan
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, ahas the value 2, and bhas the value 1. Because intis a value type, b = atakes 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 = amerely assigns the reference rather than the value. So band aboth refer to the same object. Hence, after a.MyProperty = 2executes, b.MyProperty == 2since aand brefer to the same object.
因为类是引用类型,所以b = a只分配引用而不是值。所以b和a两者都指向同一个对象。因此,在a.MyProperty = 2执行之后,b.MyProperty == 2sincea和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 arrayis actually a reference, because int[]is a reference type. So arrayis a referencethat is passed by value.
变量array实际上是一个引用,因为它int[]是一个引用类型。按值传递array的引用也是如此。
Thus, modifications made to arrayinside the function are actually applied to the int[]object to which arrayrefers. And so those modifications are visible to all references that refer to that same object. And that includes the reference that the caller holds.
因此,array对函数内部所做的修改实际上应用于int[]所array引用的对象。所以这些修改对所有引用同一个对象的引用都是可见的。这包括调用者持有的引用。
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 forloop 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 arrayis passed by value, the caller does not see that new object.
还有一个更复杂的问题。该for循环简单加倍的每个元素int[]传递给函数。这就是调用者看到的修改。第二部分是将新int[]对象分配给局部变量array。这对调用者是不可见的,因为它所做的只是改变引用的目标array。由于引用array是按值传递的,调用者看不到那个新对象。
If the function had been declared like this:
如果函数是这样声明的:
public static void FirstDouble(ref int[] array)
then the reference arraywould have been passed by reference and the caller would see the newly created object { 11, 12, 13 }when the function returned.
然后引用array将通过引用传递,调用者将{ 11, 12, 13 }在函数返回时看到新创建的对象。
回答by Servy
All method parameters are passed by value unless you specifically see refor 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.
引用本身仅在您为其分配新数组时才会更改,这就是为什么这些分配不会反映在调用者中的原因。当您取消引用对象(此处为数组)并修改基础值时,您不会更改变量,只是它指向的内容。这种变化也会被调用者“看到”,即使变量(即它指向的)保持不变。
回答by user1570129
What a confusing use of terms!
多么令人困惑的术语使用!
To clarify,
澄清,
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 bymyArraywill affect the content of the original object.However, since the 'value' of
myArrayitself is a copy, any change to this 'value' will not affect the original object nor its contents.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 meansrefArrayis actually the original address of the object itself, not a copy. Hence, any change to the 'value' ofrefArray, or the content pointed to byrefArrayis a direct change on the original object itself.
对于方法
foo(int[] myArray),“按值传递引用(对象)”实际上意味着“传递对象地址(引用)的副本”。此“副本”的值,即。myArray, 最初是原始对象的地址(引用),这意味着它指向原始对象。因此,对指向的内容的任何更改myArray都会影响原始对象的内容。但是,由于其“值”
myArray本身是一个副本,因此对该“值”的任何更改都不会影响原始对象及其内容。对于方法
foo(ref int[] refArray),“通过引用传递引用(对象)”意味着“传递对象的地址(引用)本身(而不是副本)”。这意味着refArray实际上是对象本身的原始地址,而不是副本。因此,对 的“值”refArray或指向的内容的任何更改refArray都是对原始对象本身的直接更改。

