-1

I've read quite a bit about this, but I think it's only gotten me even more confused. To strip down the issue, here's what I want to do:

public sealed partial class MainPage : Page
{
    MyFirstDataType Object1 = new MyFirstDataType();
    MySecondDataType Object2;

    void Button_Click_Event_Handler(Object sender, RoutedEventArgs e)
    {
        Object2 = new MySecondDataType(Object1);
        Object2.DoSomethingUseful();
    }
}

Now in the definition for MySecondDataType:

public class MySecondDataType
{
    MyFirstDataType MyObject;

    internal MySecondDataType(MyFirstDataType arg)
    {
        MyObject = arg;
    }

    public void DoSomethingUseful()
    {
        //modify MyObject in some way
    }
 }

So basically I've passed an object to a constructor of another class where I "copy" the object to an internal data member of that class. What I want is that every time the DoSomethingUseful() function executes, the changes it makes to MyObject should reflect in the original Object1 on my main page.

From what I've read so far, if I'd simply modified the passed object inside the constructor like arg.counter = 1, the change would have reflected in the original object too, but the issue arises when I write MyObject = arg; which creates a separate copy of the object independent from the original. How do I get around this? Or is my understanding of passing by reference flawed? (I have a hunch it is).

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Ali250
  • 652
  • 1
  • 5
  • 19

4 Answers4

1

where I "copy" the object to an internal data member of that class

Well, that is a mistake. Objects passed are not copied. Their reference is copied. If you now would call MyObject.SomeVar = 1, the original object's SomeVar will change too, since there is just one object.

Resetting MyObject = SomethingElse will decouple the two and your changes to MyObject will not reflect in the first object.

There is a good read-up in the C# programming guide: Passing Reference-Type Parameters.


As a follow up: string is a reference type that is immutable. You can't change it, ever. Even not when having two variables in the same scope. You can use a wrapper class to wrap the string, which makes the passing easier.

public class Wrapper<T>
{
    public T Value {get;set;}
}

internal MySecondDataType(Wrapper<MyFirstDataType> arg) { }

And you can set the value:

arg.Value = ...;

Then call it like this:

var w = new Wrapper<MyFirstDataType>(Variable1);
Object2 = new MySecondDataType(w);

Then use the updated Value from the wrapper class.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • It's not happening. I'm testing with `string` instead of `MyFirstDataType` and when I modify the "copy" from within `DoSomethingUseful()`, the original string in main page is unmodified. – Ali250 Jan 11 '15 at 15:01
  • `string` is the biggest exception of all. It [is an immutable reference type](http://msdn.microsoft.com/en-us/library/362314fe.aspx). – Patrick Hofman Jan 11 '15 at 15:01
  • 2
    You just have found the only data type where an exception is made because strings are immutable there is no way to change a string instance in .NET. – Alois Kraus Jan 11 '15 at 15:02
  • 2
    "string is the only reference type that is immutable"? Isn't it pretty easy to create an immutable class? – Eren Ersönmez Jan 11 '15 at 15:08
  • @Ali250 There is no way to modify a `string`, so that would explain why the original is unmodified. – JLRishe Jan 11 '15 at 15:10
  • Oh. And I'm assuming `int` and other primitive types definitely won't work since they'll be treated as value-type parameters? – Ali250 Jan 11 '15 at 15:10
  • @PatrickHofman Just remove the part that says "is the only reference type that". – JLRishe Jan 11 '15 at 15:11
  • @Ali250: You are right. You can use `ref` on them too. – Patrick Hofman Jan 11 '15 at 15:11
  • @PatrickHofman I don't think there is any way for MySecondDataType to keep a ref copy of the passed in MyFirstDataType since fields cannot be ref. Either don't do MyObject = somethingElse, or pass in a reference to the MainPage instead of MyFirstDataType. – Eren Ersönmez Jan 11 '15 at 15:22
  • @ErenErsönmez: True. A wrapper class might be better in this case. – Patrick Hofman Jan 11 '15 at 15:26
0

There is no copy being made. One reference being made with the new operator. You're passing this object to SecondDataType. The both refer the the same object.

Sievajet
  • 3,443
  • 2
  • 18
  • 22
0

Even if you pass MyFirstDataType class object to constructor of MySecondDataType its copy but copy of reference of object your are passing and not copy of object itself. Essentially its creating copy of reference. May be this example will help you to understand it.

public class A
{
    int count=0;
    public void Increment()
    {
        count++;
    }
}

public class B
{
    A a;
    public B(A a)
    {
        this.a = a;
    }
}

and then

  private void button2_Click(object sender, EventArgs e)
    {
        A a = new A();
        B b = new B(a);
        a.Increment(); //Increment count of a
        //If you check value of count of a in b after above line it should be 1.
    }
Pankaj Kapare
  • 7,486
  • 5
  • 40
  • 56
0

I think that your understanding of passing by reference is broadly correct. Reading your question, I believe that in your example, the update you've given in the example should work. As specified in other answers, you're actually copying a pointer to the first object, so the object is, essentially, the same.

My guess is that when you state:

the changes it makes to MyObject should reflect in the original Object1 on my main page.

You're not implementing INotifyPropertyChanged or equivalent.

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