27

これらは、私が読んでいる 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 };

基本的に、私が知りたいコードは、元の呼び出し元がメソッドによって変更されないよりも配列が値で渡された場合に本が言っているということです(私が理解していることから)。そのため、メソッド FirstDouble の終わりに向かって、ローカル変数配列を新しい要素セットに割り当てようとしましたが、失敗し、表示されたときの元の呼び出し元の新しい値は 2,4,6 です。

今私の混乱は、メソッド FirstDouble の for ループが元の呼び出し元の firstArray を値で渡された場合に 2,4,6 に変更した方法です。値は 1,2,3 のままにしておくべきだと思いました。

前もって感謝します

4

4 に答える 4

60

これを理解するための鍵は、値型と参照型の違いを知ることです。

たとえば、典型的な値型を考えてみましょうint

int a = 1;
int b = a;
a++;

このコードが実行された後a、値は2になりb、値はになります1intは値型であるため、b = aの値のコピーを取りますa

次に、クラスについて考えます。

MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;

クラスは参照型であるためb = a、値ではなく参照を割り当てるだけです。したがってba両方が同じオブジェクトを参照します。したがって、a.MyProperty = 2実行後b.MyProperty == 2、同じオブジェクトaを参照します。b


質問のコードを考慮すると、配列は参照型であるため、この関数では次のようになります。

public static void FirstDouble(int[] array)

は参照型であるため、変数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 };
}

もう1つの問題があります。forループint[]は、関数に渡されるの各要素を単純に2倍にします。これは、発信者に表示される変更です。int[]2番目の部分は、ローカル変数への新しいオブジェクトの割り当てですarray。参照のターゲットを変更するだけなので、これは呼び出し元には表示されませんarray。また、参照arrayは値によって渡されるため、呼び出し元にはその新しいオブジェクトは表示されません。

関数が次のように宣言されている場合:

public static void FirstDouble(ref int[] array)

その場合、参照arrayは参照によって渡され{ 11, 12, 13 }、関数が返されたときに呼び出し元は新しく作成されたオブジェクトを見ることになります。

于 2012-04-25T23:43:06.717 に答える
14

用語の使い方が紛らわしい!

明確にするために、

  1. メソッドの場合foo(int[] myArray)「参照 (オブジェクト) を値で渡す」とは、実際には「オブジェクトのアドレス (参照) のコピーを渡す」ことを意味します。この「コピー」の値、つまり。myArrayは、最初は元のオブジェクトのアドレス (参照) であり、元のオブジェクトを指すことを意味します。したがって、 が指すコンテンツへの変更myArrayは、元のオブジェクトのコンテンツに影響します。

    ただし、myArrayそれ自体の「値」はコピーであるため、この「値」を変更しても、元のオブジェクトやその内容には影響しません。

  2. メソッドの場合foo(ref int[] refArray)「参照 (オブジェクト) を参照で渡す」とは、「オブジェクトのアドレス (参照) 自体 (コピーではない) を渡す」ことを意味します。つまりrefArray、実際にはオブジェクト自体の元のアドレスであり、コピーではありません。したがって、 の「値」refArray、または が指すコンテンツへrefArrayの変更は、元のオブジェクト自体に対する直接の変更です。

于 2017-09-01T06:14:28.377 に答える
7

ref特にまたはが表示されない限り、すべてのメソッド パラメータは値によって渡されますout

配列は参照型です。これは、参照を値で渡していることを意味します。

参照自体は、新しい配列を割り当てたときにのみ変更されます。これが、これらの割り当てが呼び出し元に反映されない理由です。オブジェクト (ここでは配列) を逆参照して基になる値を変更すると、変数は変更されず、それが指すものだけが変更されます。この変更は、変数 (変数が指すもの) が一定のままであっても、呼び出し側にも「表示」されます。

于 2012-04-26T01:07:02.767 に答える