5

If we modify the content of the array passed as parameter inside a method the modification is done on the copy of the argument instead of the original argument hence the result is not visible.

What is the process that happens when we call method that have reference type argument?

Here is the code sample of what I want to ask

      using System;

namespace Value_Refrence_Type
{
    class Program
    {
        public static void Main()
        {
            int[] callingarray = { 22, 200, 25485 };
            abc(callingarray);
            Console.WriteLine("This is callingarray");
            foreach (int element in callingarray)
                Console.WriteLine(element);
        }



        //method parameter
        static void abc(int[] calledarray)
        {
            Console.WriteLine("Method Called--------");
            foreach (int element in calledarray)
                Console.WriteLine(element);

            //Here on changing the value of elements of calledarray does't afftect the value of element of callingarray
            //if both refrences to same memory location then the value needs to change, which is not happening here
            calledarray = new int[] {55, 54, 65};
            foreach (int element in calledarray)
                Console.WriteLine(element);
        }

    }
}
mdadil2019
  • 807
  • 3
  • 12
  • 29
  • 8
    @nicomp arrays or any other object are not passed by reference. All objects in C# are passed by value by default. To pass by reference you need to use the `ref` or `out` keyword. You seem to be confusing reference types with argument passing. – InBetween May 28 '16 at 12:12
  • Possible duplicate of [What's the difference between passing by reference vs. passing by value?](http://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value) – Uwe Keim May 28 '16 at 12:31
  • 6
    @nicomp again, you are confusing the behavior of a reference type passed by value with passing an argument by reference. When passing by reference you can assign a new array to the argument and it will change the variable at the callsite which is clearly not the case in the code we are discussing. Again, it's very simple, to pass an argument by reference you need to use the provided keywords `ref` or `out`, otherwise it will be passed by value. I suggest you read the related areas of the C# specifications if you remain unconvinced. – InBetween May 28 '16 at 13:00
  • 3
    @nicomp funny that you point to my own answer. I see you are unconvinced, so I'll quote [MSDN](https://msdn.microsoft.com/en-us/library/0f66670z.aspx) here: *"(...) To pass a parameter by reference, use the ref or out keyword. (...)"*. – InBetween May 28 '16 at 13:23
  • 9
    @nicomp No, I see a *parameter being passed by value* which means the variable is copied. Because the variable holds a reference type, the reference is copied and it point to the same object. But **that is not passing a parameter by reference**. Passing an argument by reference entails using the `ref` keyword and it allows you to change at the callsite the *value* of the original variable, that is I could say `a = null` and back at the callsite the variable would be `null` when the method returned. Try that in your example and see how it works. Again, just read the link in my previous answer. – InBetween May 28 '16 at 13:50
  • 1
    This pedantry about "passing references by value" is useless. Everyone knows that object references are passed by value in C#. But we say that objects are "passed by reference" in normal conversation anyway, because we're interested in the *assignment behavior of the object,* not the underlying implementation details. – Robert Harvey May 28 '16 at 13:52
  • 3
    @RobertHarvey well it might be pedantry to you but there is an important semantic difference. How do you differentiate your simple "pass by reference" form the case where you use `ref` then. These pedantries at least help being concise. – InBetween May 28 '16 at 13:54
  • 7
    @RobertHarvey That's not *too* problematic in conversations among people that actually understand what's going on behind the scenes, but for those that don't understand what's actually going on, like nicomp, it creates a severly incorrect mental model of what's going on, which *results in the program not behaving as they expect it to* because they think they're passing values by reference when they aren't. If passing a reference by value and a value by reference actually has the same semantics, then differentiating between them wouldn't be important, but they *don't* have the same behavior. – Servy May 28 '16 at 13:54
  • 1
    @inBetween: Eh, I think you're right. The OP is confusing the reference with the actual array. Personally, I've always found the nomenclature "reference types are passed by value" confusing. You're referring in that sentence to the actual reference, not the array, which we won't care about 95% of the time. – Robert Harvey May 28 '16 at 13:59
  • 2
    @nicomp: You should read http://pobox.com/~skeet/csharp/parameters.html and concentrate on the difference between "passing a reference by value" and "passing something by reference". They really are different things. – Jon Skeet May 28 '16 at 14:39
  • 1
    @RobertHarvey: My experience is that it all makes sense if you start by saying "What's the value of the `callingarray` variable? It's not an array. It's a reference. When you call the method, that value is passed into the method..." *So* many things make more sense when you understand that the value of the variable isn't the array (or object in general) - I wish people spent more time being precise on that front :( – Jon Skeet May 28 '16 at 14:40
  • 1
    @JonSkeet: Sure, but if you have to put significant thought into whether or not an array *reference* in a variable is being replaced, I would suggest that the design of the code could probably be improved. I understand why `ref` exists, but I can't imagine when I would ever use it on a reference variable. That would be akin to *changing out the array for another one inside a function;* I would `return` a new array before I ever used a `ref`. – Robert Harvey May 28 '16 at 15:23
  • 1
    @RobertHarvey: That's fine if you've only got a single value to return. It doesn't help if you have a return value already, although admittedly that's rare. `ref` can also be useful if you want to *conditionally* replace values. I can't say I use it terribly often, but the main thing is to understand what it means to start with. The business about "the value of the variable is a reference, not an object" is important in Java as well, which doesn't even have pass by reference. – Jon Skeet May 28 '16 at 15:28
  • 1
    Seems as if @JonSkeet's answer [here](http://stackoverflow.com/a/8708674/102937) provides a pretty clear explanation. – Robert Harvey May 28 '16 at 15:41

4 Answers4

10

No, that is not correct.

Arguments are passed by value by default in C#, which means you get a copy of the variable. But it's important to realize that what is copied is just the variable, not necessarily the object; if the variable holds a reference type (an array for example) then the variable is really just a "pointer" to a memory address where the object lives. So when you pass said variable to a method call, the reference is copied yes, but it still points to the exact same object the original variable refers to.

Things are very different when the argument is a value type. In that case the variable itself holds the object and therefore you'd get the behavior you seem to be expecting.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • but when I change the value of parameter (which is array) in method declaration then the value is not visible when I called the method instead it shows the value of array that is before the changing in method declaration. – mdadil2019 May 28 '16 at 12:28
  • @MohammadAdil exactly, because you are changing a *copy* of the original reference. If you want to change what the original variable is pointing at then you need to pass the argument by reference. – InBetween May 28 '16 at 12:45
  • 1
    Then what the lines in the image(book) want to explain, is it wrong? – mdadil2019 May 28 '16 at 12:47
  • 3
    @MohammadAdil No. Modifying an element of the array, `a[1] = 1;` will persist because the argument is pointing to the same object the original variable is. However doing the following `a = new[] { ...}` will *not* persist because you are assigning a new reference to a copy of the original variable. The original variable or the array it's pointing to have no idea and don't care that you just assigned a new array to a copy that was made of the variable. – InBetween May 28 '16 at 12:52
8

Here are many answers with a description. I try to give an example. Let's say this is your method:

public void ProcessData(int[] data)
{
  data[0] = 999;
}

If you call the method like this:

int[] dataToProcess = new int[] {1, 2, 3};
ProcessData(dataToProcess);
Console.WriteLine(dataToProcess[0]); //returns 999;

it will return 999 because ProcessData accesses the memory of the array.

Like @InBetween described:

Arguments are passed by copy by default in C#, but what is copied is the variable

That means, if you set the data in your method to null:

public void ProcessData(int[] data)
{
  data = null;
}

it would not set your dataToProcess to null. This means:

You are passing the copy of a pointer to the memory of your array to the method.

Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49
1

Arrays are a reference type in C#. This means that each time an array is passed as an argument to any function, the reference (or pointer) to the argument is passed to the function. Thus any modifications you make to the array in the function are made in the actual argument also.

If we modify the content of the array passed as parameter inside a method the modification is done on the copy of the argument instead of the original argument hence the result is not visible.

The behavior you are referring to here is for value types and not reference types. Value types in C# are structs and enums, and reference types in C# are classes and arrays.

EvilTak
  • 7,091
  • 27
  • 36
  • there is same thing happening with array what I explained in my question.If I make changes in method declaration then the result is not displayed when I called the method. – mdadil2019 May 28 '16 at 12:32
  • In c# arguments is passed to parameter by value (default) to pass arguments by reference we have to use ref or out keyword. – mdadil2019 May 28 '16 at 14:20
1

Arrays in c# can be passed as arguments to method parameters. Because arrays are reference types, the method can change the value of the elements.For further you should look out to this msdn doc.

Himanshu Dwivedi
  • 7,934
  • 3
  • 31
  • 52
  • 1
    `Because arrays are reference types, the method can change the value of the elements.` Arrays aren't mutable *because* they're reference types. It's mutable, and a reference type. There's no causation there. – Servy May 28 '16 at 13:56
  • I found the link to contain helpful example. Thanks. – niki b Aug 06 '17 at 05:41