C # ref Confusion

I have a confusion that when I pass a refrence variable in the constructor of another class and after passing that refrence object, I recreate the refrence object with a new keyword.

Now the class I passed the overridden object does not reflect the updated data. Below is the problem above:

The object to be passed using Refrence:

public class DummyObject
{
    public string Name = "My Name";

    public DummyObject()
    { }
}

      

The class that passes the Refrence value:

public partial class Form1 : Form
{
    // Object to be passed as refrence
    DummyObject dummyObject = new DummyObject();

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // assigning value
        dummyObject.Name = "I am Dummy";

        // Passing object
        Form2 frm = new Form2(ref dummyObject);
        frm.Show();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        // Displaying Name
        MessageBox.Show(this.dummyObject.Name);
    }

    private void button3_Click(object sender, EventArgs e)
    {
        // Assigning new object
        this.dummyObject = new DummyObject();

        // Changing Name Variable
        this.dummyObject.Name = "I am Rechanged";

        // Displaying Name
        MessageBox.Show(this.dummyObject.Name);
    }
}

      

The class to which the object is passed by reference:

public partial class Form2 : Form
{
    private DummyObject dummyObject = null;

    public Form2(ref DummyObject DummyObject)
    {
        InitializeComponent();

        this.dummyObject = DummyObject;
        this.dummyObject.Name = "I am Changed";
    }

    private void button2_Click(object sender, EventArgs e)
    {
        MessageBox.Show(this.dummyObject.Name);
    }
}

      

whn I reaasign the object in Form 1 and cdisplay its value in Form 2, it still displays "I have changed" instead of "I have been revised".

How do I sync data?

+2


a source to share


6 answers


You cannot sync variables this way; there is no concept of ref

instance or static variables, only parameters ref

. An instance variable dummyObject

does (and always will) represent a single memory slot. All you do is copy the value from the parameter dummyObject

to dummyObject

; you are not doing anything that will affect whether the parameter is declared as ref

.

The typical way is to show the value dummyObject

as a property on Form2

.

public DummyObject DummyObject
{
    get { return dummyObject; }
    set 
    { 
        dummyObject = value;

        // any other code, if any, that might need to execute 
        // when the value is changed
    }
}

      

But that means you need to hold on to your instance Form2

so that you can change the value of the property.

Another option, albeit somewhat confusing, would be to pass in the wrapper class that contains this property, rather than add it to the form.



public class DummyWrapper
{
    public DummyObject DummyObject { get; set; }
}

      

Then you change your forms to use DummyWrapper

instead dummyObject

, then access the property dummyWrapper.DummyObject

when you want to get or set a value. Uas long, since you are changing the property value dummyWrapper.DummyObject

and not the actual value DummyWrapper

, then you will point to the same instance.

For instance:

public partial class Form2 : Form 
{ 
    private DummyWrapper dummyWrapper = null; 

    public Form2(DummyWrapper dummyWrapper) 
    { 
        InitializeComponent(); 

        this.dummyWrapper = dummyWrapper;
        this.dummyWrapper.DummyObject.Name = "I am Changed"; 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
        MessageBox.Show(this.dummyWrapper.DummyObject.Name); 
    } 
} 

      

+2


a source


I think you misunderstood what this key does. When you pass a dummyObject to Form2's constructor, Form2 does not bind its own dummyObject field to the dummyObject field in Form1.

You can keep data in sync by avoiding creating new DummyObject instances, or by making Form1 tell Form2 whenever it creates a new instance.



In reality, you really don't need to use the ref keyword, it won't make any difference if you must remove it.

+4


a source


You misunderstood what "ref" does. The best way to explain what "ref" is is that it aliases the variable. When you say

void M(ref int x)
{
    Console.WriteLine(x);
    x = 10;
}
...
int y = 123;
M(ref y);

      

what you say at the calling site is "x is now a different name for the variable y". That is, it is exactly as if you just said

int y = 123;
Console.WriteLine(y);
y = 10;

      

x is an alias for y. Unfortunately, we chose the word "ref" to mean "make an alias for a variable" because it is confusing, but that's what the language designers chose.

Now if you said

void N(int z)
{
    Console.WriteLine(z);
    z = 10;
}
...
int y = 123;
N(y);

      

which doesn't make z an alias for y. This code is the same as

int y = 123;
int z = y;
Console.WriteLine(z);
z = 10;

      

which does not change the value of y as z and y are two different variables, whereas x and y are two different names for the same variable.

+2


a source


The keyword ref

won't give you this opportunity. Instead, it allows you to re-assign a passed variable to a new instance, but only in the context of a method. To clarify:

void SomeMethodWithRef(ref DummyObject dummy)
{
    dummy = new DummyObject(){Name="Modified"};
}

void CallingMethod()
{
    DummyObject obj = new DummyObject(){Name="Original"};
    SomeMethodWithRef(ref obj);
    // at this point, obj has Name="Modified";
}

      

However, in your case, you are storing the object reference as a field that has completely different semantics - reassigning that field is different from redefining the original variable.

To keep data in sync, either work with the same instance when changes are made (for example this.dummyObject.Name = "I am changed";

) instead of creating a completely new instance, or you will need to create a mechanism to propagate those changes between forms (for example, your forms implement INotifyPropertyChanged

and subscribe to property change notifications each other).

0


a source


The reason it doesn't do what you want is because the first line of Form1.button3_click creates a second DummyObject instance. This new instance is never sent to Form2, so Form2 only has a copy of the old instance. Now Form1 and Form2 have different objects, hence different messages.

The ref keyword will only be used in your example if the Form2 constructor wanted to assign a new instance to the OUT path parameter (it differs from the out parameter because it is a two-way path). This assignment will change the value of the Form1.dummyObject field.

0


a source


I revisited my app using a property suggested by Adam Robinson for syncing. Now my code has been modified as shown below and gives the desired results.

The class containing the data to be synchronized:

public class DummyObject
{
    public string Name = "My Name is this.";        

    public DummyObject()
    { }        
}

      

The class that creates a new Inctance and reassigns it to Property:

public partial class Form1 : Form
{
    // Instance of DummyObject
    DummyObject dummyObject = new DummyObject();

    // Create Instance of Form2
    Form2 frm2 = new Form2();

    public Form1()
    {
        InitializeComponent();            

        // Assign DummyObject to Form2.DummyObject property
        frm2.DummyObject = this.dummyObject;

        // Change Form2 DummyObject.Name
        frm2.DummyObject.Name = "I am changed for Form2.";

        // Display Form2
        frm2.Show();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(this.dummyObject.Name);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        // Change Name of Form1 DummyObject
        this.dummyObject.Name = "I am changed from Form1.";
    }

    private void button3_Click(object sender, EventArgs e)
    {
        // Assign new Instance
        this.dummyObject = new DummyObject();

        // Change Name value
        this.dummyObject.Name = "I am rechanged from Form1.";

        // Reassign Form2.DummyObject the newly created instance
        // for synchronization purposes
        this.frm2.DummyObject = this.dummyObject;         
    }       
}

      

Class separating an object by property:

public partial class Form2 : Form
{
    private DummyObject dummyObject;

    public Form2()
    {
        InitializeComponent();
    }

    public DummyObject DummyObject
    {
        get { return this.dummyObject; }
        set { this.dummyObject = value; }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(this.dummyObject.Name);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        this.dummyObject.Name = "I am changed from Form2.";            
    }
}

      

Thank you everyone for your prompt reply.

0


a source







All Articles