0

I have the following code:

   static void Main(string[] args)
    {
        myclass c = new myclass();

        c.test1 = 1;

        myclass c2 = TestPassByValByRef(c);

        Console.WriteLine("c.Test1: {0}", c.test1);
        Console.WriteLine("c2.Test1: {0}", c2.test1);
        Console.ReadLine();
    }

    private static myclass TestPassByValByRef(myclass c)
    {
        Console.WriteLine("Before NowPassByRef c.Test1: {0}", c.test1);
        NowPassByRef(ref c);
        Console.WriteLine("After NowPassByRef c.Test1: {0}", c.test1);

        return c;
    }

    private static void NowPassByRef(ref myclass c)
    {
        c = new myclass();
        c.test1 = 10;
        c.test2 = 25;
    }

The output is that c2 retains the changed value, whereas c does not. My question is this: What happens to c in TestPassByValByRef?

Paul Michaels
  • 16,185
  • 43
  • 146
  • 269

4 Answers4

2

When you call TestPassByValByRef there are two references to your object - the reference in Main, and the reference for the parameter to TestPassByValByRef. This is because passing a reference type (anything that isn't a struct) in C# 'by value' actually passes the reference by value, not the object itself. Thus, the reference is copied and there are now two references to the original object.

After the call to NowPassByRef, TestPassByValByRef's copy of the reference has been overwritten by a reference to a new instance of myclass, but since there's still the reference in Main the object is not eligible for garbage collection.

So, the short answer to "what happens" is "nothing".

Matthew Walton
  • 9,809
  • 3
  • 27
  • 36
0

In first case you pass by value a reference to your object.

So when you do in first case you make new, you reinitialize the copy of the reference, so it looses the relation with original object.

In second case you pass a reference itself, so reinitializing it with new you change also the memory location where it points.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • I didn't downvote, but many people try to avoid conflating pointers and references, especially in languages where both exist (which includes C#) – Damien_The_Unbeliever Jun 20 '12 at 14:54
  • @Damien_The_Unbeliever: changed to REFERENCE. But not understanding someone post could not be a reason to downvote it, seems to **me** – Tigran Jun 20 '12 at 14:57
0

In your following code you c = new myclass(); create a new memory reference for object c which does not point to the passed. Due to this you are not getting the changes reflected to your first object that you created.

private static void NowPassByRef(ref myclass c)
    {
        c = new myclass();  // it will create new memory reference
        c.test1 = 10;
        c.test2 = 25;
    }

so it will show c does not get changed and output as:

Before NowPassByRef c.Test1: 1
After NowPassByRef c.Test1: 10
c.Test1: 1
c2.Test1: 10

For a while just comment the c = new myclass(); in the method and it will reflect the changes to the object c. it will clear your doubt about the reference pointer etc.

private static void NowPassByRef(ref myclass c)
        {
            //c = new myclass();  // it will create new memory reference
            c.test1 = 10;
            c.test2 = 25;
        }

Now output will be:

Before NowPassByRef c.Test1: 1
After NowPassByRef c.Test1: 10
c.Test1: 10
c2.Test1: 10

I think this - C# pass by value/ref? must be your explained information for your question and check John Skeet's article on Parameter passing in C#.

Community
  • 1
  • 1
Niranjan Singh
  • 18,017
  • 2
  • 42
  • 75
  • Just to be clear - what I'm questioning is not why the value is not retaining its changed value, but why IS. What I expected to happen for this code sample was for the value to remain as was. – Paul Michaels Jun 20 '12 at 15:29
  • @pm_2: I think you have not ridden answer completely.. I am not focusing on output, just shown you it is changing reference and you need to go through these links... – Niranjan Singh Jun 21 '12 at 01:41
0
static void Main(string[] args)
{
    myclass c = new myclass();

    c.test1 = 1;

    myclass c2 = TestPassByValByRef(c);

    Console.WriteLine("c.Test1: {0}", c.test1);
    Console.WriteLine("c2.Test1: {0}", c2.test1);
    Console.ReadLine();
}

main contains two references, both of which can refer to objects of type myclass. c is initialized before TestPassByValByRef, c2 is initialized by the return value of that method.

private static myclass TestPassByValByRef(myclass c)
{
    Console.WriteLine("Before NowPassByRef c.Test1: {0}", c.test1);
    NowPassByRef(ref c);
    Console.WriteLine("After NowPassByRef c.Test1: {0}", c.test1);

    return c;
}

TestPassByValByRef contains a single reference called c. It initially contains a copy of the reference that was passed to it as a parameter (because that parameter was passed by value). This reference is then passed by reference to NowPassByRef and returned.

private static void NowPassByRef(ref myclass c)
{
    c = new myclass();
    c.test1 = 10;
    c.test2 = 25;
}

NowPassByRef shares a reference c with its calling method. It immediately reassigns it to a new value before returning.


What did you expect to happen?

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448