1

Consider the following case:

public class Test
{
    public Test()
    {
        text = "By default";
    }
    public string text { get; set; }
    public void GiveMeClass(Test t)
    {
        t.text = "I have a class";
    }
    public void GiveMeRef(ref Test t)
    {
        t.text = "I have a ref";
    }
}

calling code:

Test t = new Test();
Console.WriteLine(t.text);

t.GiveMeClass(t);
Console.WriteLine(t.text);

t.GiveMeRef(ref t);
Console.WriteLine(t.text);

this will writeline the following texts:

By default
I have a class
I have a ref

Now if we change code in the methods by assigning t new instance of Test class, like in the code below:

public class Test
{
    public Test()
    {
        text = "By default";
    }
    public string text { get; set; }
    public void GiveMeClass(Test t)
    {
        t = new Test() { text = "I have a class" };
    }
    public void GiveMeRef(ref Test t)
    {
        t = new Test() { text = "I have a ref" };
    }
}

the calling code will writeline the following texts:

By default
By default
I have a ref

As you can see the instance of Test class did not change when GiveMeClass method was called (because the output text was "By default", not "I have a class"). So the question is, if the classes are passed by reference to methods why did not the assignment t = new Test() { text = "I have a class" }; change the original instance of Test class in the caller code?

user1080381
  • 1,597
  • 1
  • 16
  • 22

3 Answers3

1

Classes are passed always by reference, but the change:

t = new Test() { text = "I have a class" }; // this is t2 (new class instance is created and assigned into t valid only for this method)

will not be reflected, because the point, where the method was called:

Test t = new Test();        // this is t1
t.GiveMeClass(t);           // this is t1 on input and will not change
Console.WriteLine(t.text);  // this is still t1

will not change the first assignment, only rewrites the assignment in the function GiveMeClass

Julo
  • 1,102
  • 1
  • 11
  • 19
  • So what is the difference between reference arguments in GiveMeClass and GiveMeRef methods? Is it just by how it is designed or is there any logical flow behind? As you have mentioned new reference of new instance will be assigned to t in GiveMeClass method and the initial class wont be changed, but why it is not the same in GiveMeRef method? – user1080381 Sep 05 '18 at 08:06
  • @user1080381: Consider the "ref" version as there would be a return parameter with automatic assignment; When you know C there is an example: in `RefData(char *data)` *(call: `char[10] text = "text"; RefData(text);` you can change the data content, but when you change the assignment in function, the assignment in `text`will remain the same. To change the the `text` you need `RefVariable(char **data)` *(call: `char[10] text = "text"; char *ref = text; RefVariable(&ref);`. The `ref` variable will be changed, when you change the assignment in the function `RefVariable`. – Julo Sep 05 '18 at 08:18
1

The answer here is exactly what you're looking for. Please read it. In summary, the default convention for parameters in C# is pass by value. This is true whether the parameter is a class or struct . In the class case just the reference is passed by value while in the struct case a shallow copy of the entire object is passed. This creates a new object and points Test class to it.

0

In the method below t is a reference to the original object and it is passed by value and not by reference.

 public void GiveMeRef(Test t -> a copy of t that points to original object address)
{
    t = new Test() { text = "I have a class" }; -> the copy of t is now pointing to a new object 
}

Hence when you are displaying the results the original t variable still points to the object test (which has the text "by default")

t.GiveMeRef(ref t);
Console.WriteLine(t.text);
user3785553
  • 121
  • 6