-1

I'm passing a reference type (Proto3 generated) to a method to update some properties. When the method returns, the properties have reverted back as if it's not being passed by reference or are immutable.

MyData dest = new MyData();
dest.Num = 1;

MyData src = new MyData();
src.Num = 2;

Console.WriteLine(dest.Num); // num = 1
Test(src, dest);
Console.WriteLine(dest.Num); // num still equals 1

public static void Test(MyData src, MyData dest)
{
    // dest.Num = 1 here
    dest = src;
    // dest.Num = 2 now
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
user3953989
  • 1,844
  • 3
  • 25
  • 56
  • 4
    You've just changed the value of the `dest` parameter. That's a parameter which is passed by value - you're not using `ref`. If instead you used `dest.Num = 3;` that would change the content of the object that `dest` refers to. See http://pobox.com/~skeet/csharp/parameters.html - note that this has nothing to do with Protobuf, it's just how C# works in general. – Jon Skeet Dec 31 '18 at 18:33
  • I actually just read your article yesterday trying to wrap my head around this. Just to validate, value types and reference types are passed by value unless you use the `ref` keyword. However you can still modify the data the reference type references without `ref`. You just can't change the actual reference itself? – user3953989 Dec 31 '18 at 18:48
  • 1
    Yes, exactly. If you haven't read http://pobox.com/~skeet/csharp/references.html yet, I'd read that too. – Jon Skeet Dec 31 '18 at 19:18

2 Answers2

1

src and dest are passed by value. When you assign dest=src, you're just assigning src to a local variable that used to point to dest, which does not affect dest itself.

You can, of course, modify dest inside a method by modifying its members if you want to, e.g.:

public static void Test(MyData src, MyData dest)
{
    dest.Num = src.Num;
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
0

Your choice to reuse variable names may be confusing the problem. Let's fix that:

MyData foo = new MyData();
foo.Num = 1;

MyData bar = new MyData();
bar.Num = 2;

Console.WriteLine(foo.Num); // num = 1
Test(bar, foo);
Console.WriteLine(foo.Num); // num still equals 1

public static void Test(MyData src, MyData dest)
{
    // dest.Num = 1 here
    dest = src;
    // dest.Num = 2 now
}

Now let's look at what Test does. It reassignes the value of dest to src. It does NOT change the values of the object that either dest or src referenced at all. So foo and bar in the calling function still reference the same objects, so your result is expected.

If you have made dest a ref variable in Test, then you would have seen foo change because Test would change the actual reference.

D Stanley
  • 149,601
  • 11
  • 178
  • 240