Frage

How is it possible to change the values of an array a from the inside of SumElemtnts method? Is it because it's a static method? Because the method returns only the variable sum and there is no ref or out.

class Program
{
    public static int SumElements(int[] a)
    {
        int[] a2 = a;
        int sum = 0;
        for (int i = 0; i < a2.Length; i++)
        {
            int temp = a2[i] * 10;
            a2[i] = temp;
            sum += temp;
        }
        a[a2.Length - 2] = sum;
        return sum;
    }

    public static void Main(string[] args)
    {
        int[] a = { 1, 2, 3 };
        int sum = SumElements(a);

        Console.Write("Sum = " + sum + ", ");
        for (int i = 0; i < a.Length; i++)
        {
            Console.Write(a[i] + " ");
        }
    }
}

The result is:

Sum = 60, 10 60 30

War es hilfreich?

Lösung 2

An array is a reference type.

You're not passing in a copy of the array, you're passing in a reference to it.

Here's a smaller LINQPad program that demonstrates:

void Main()
{
    var a = new[] { 1, 2, 3 };
    Test(a);
    a.Dump();
}

public static void Test(int[] arr)
{
    arr[1] = 15;
}

Output:

1
15
3

Longer description: When you pass a value to a method in C#, it's "pass by value" as default, meaning that you're passing in a copy of the value, not the actual variable itself.

In this case you're passing in a copy of the reference, but the reference is referencing an array.

Thus the method has its own reference to the array, but it's still working with the same array as the code "on the outside".

Andere Tipps

You're not changing the value of the variable within SumElements - that still refers to the same array that it did before. Note how there's no assignment to a within the SumElements method.

Instead, you're changing the contents of the array. That change is visible within Main, because that still has a reference to the array as well.

Think of a variable as being like a piece of paper. In Main, you have a variable called a, which contains a reference - a way of getting to the array. That's like having a piece of paper with a street address on. That's the street address of a house - analogous to the array object.

You're copying that value (the street address) and using it as the value of a in SumElements. The two pieces of paper are separate - you could scribble over the one in SumElements and that wouldn't change the piece of paper in Main - but they start off with the same street address. SumElements is then going to that street address, and painting one of the windows. When Main then goes to the same street address, it sees the painted window as well... because there's only one house (the array object) even though there were two pieces of paper with the same street address written on them.

See my articles on parameter passing and reference types and value types for more details.

Your int[] a is an array (a reference type) its address gets passed as value to your method SumElements, now the parameter a in your method points to the same object in memory. So once you change the value of a particular index you see the change in your caller.

You should see: Parameter passing in C# by Jon Skeet

For the simple reason that array is reference type so you are changing the contents of the array

From MSDN:

The following example demonstrates passing a reference-type parameter, arr, by value, to a method, Change. Because the parameter is a reference to arr, it is possible to change the values of the array elements. However, the attempt to reassign the parameter to a different memory location only works inside the method and does not affect the original variable, arr. C#

class PassingRefByVal 
{
    static void Change(int[] pArray)
    {
        pArray[0] = 888;  // This change affects the original element.
        pArray = new int[5] {-3, -1, -2, -3, -4};   // This change is local.
        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
    }

    static void Main() 
    {
        int[] arr = {1, 4, 5};
        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr [0]);

        Change(arr);
        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);
    }
}

/* Output:
    Inside Main, before calling the method, the first element is: 1
    Inside the method, the first element is: -3
    Inside Main, after calling the method, the first element is: 888
*/

try to read Passing Reference-Type Parameters (C# Programming Guide) it's the best way to understand more what happen

Every reference Type is accessed with the reference to the adress the data is in (even if not marked as a reference parameter). See the list for which data types are reference types and which are value types below.. very good examples and technical details can be found here http://www.albahari.com/valuevsreftypes.aspx

Value Types Value types include the following:

All numeric data types
Boolean, Char, and Date
All structures, even if their members are reference types
Enumerations

Reference Types Reference types include the following:

String
All arrays, even if their elements are value types
Class types, such as Form
Delegates
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top