Reputation: 1333
I have a confusion that when i pass a variable by refrence in the constructor of another class and after passing that object by refrence i recreate the refrence object with the new keyword.
Now the class in which i have passed the refrenced object dosen't reflect the updated data. An exabple of the above problem is shown below:
public class DummyObject
{
public string Name = "My Name";
public DummyObject()
{ }
}
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);
}
}
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 am Changed" instead of "I am Rechanged".
How to keep the data synchronized?
Upvotes: 2
Views: 309
Reputation: 1333
I have reconsidered my application by using property as suggested by Adam Robinson for synchronization purposes. Now my code have been changed as shown below and producing the desired results.
public class DummyObject
{
public string Name = "My Name is this.";
public DummyObject()
{ }
}
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;
}
}
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.";
}
}
Thankx to every one for their prompt response.
Upvotes: 0
Reputation: 659956
You've misunderstood what "ref" does. The best way I have to explain what "ref" does is that it makes an alias to a variable. When you say
void M(ref int x)
{
Console.WriteLine(x);
x = 10;
}
...
int y = 123;
M(ref y);
what you are saying at the call site is "x is now another name for the variable y". That is, this is exactly as if you'd simply said
int y = 123;
Console.WriteLine(y);
y = 10;
x is an alias for y. It is unfortunate that we chose the word "ref" to mean "make an alias for a variable" because that is confusing, but that's what the language designers chose.
Now if you'd said
void N(int z)
{
Console.WriteLine(z);
z = 10;
}
...
int y = 123;
N(y);
that does not make z an alias for y. That code is the same as
int y = 123;
int z = y;
Console.WriteLine(z);
z = 10;
which does not change the value of y, because z and y are two different variables, whereas x and y are two different names for the same variable.
Upvotes: 2
Reputation: 1306
The reason it doesn't do what you want is the first line of Form1.button3_click, creating the 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 would be used in your example only if the constructor of Form2 wanted to assign a new instance to the parameter on the way OUT (it is different than an out parameter in that it is two-way instead of one-way). Such an assignment would change the value of the Form1.dummyObject field.
Upvotes: 0
Reputation: 185593
You cannot keep variables synchronized in this manner; there is no concept of ref
instance or static variables, only ref
parameters. The dummyObject
instance variable does (and always will) represent a distinct slot of memory. All you're doing is copying the value from the DummyObject
parameter into dummyObject
; you're doing nothing that would be affected by whether or not the parameter is being declared as ref
.
The typical way is to expose the value of 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 this means that you'll need to hold on to your instance of Form2
so that you can change the value of the property.
Another option, though somewhat convoluted, would be pass a wrapper class that contains that property, rather than adding it to the form.
public class DummyWrapper
{
public DummyObject DummyObject { get; set; }
}
You then change your forms to use a DummyWrapper
instead of a DummyObject
, then access the dummyWrapper.DummyObject
property when you want to get or set the value. Uas long as you only change the value of the DummyWrapper.DummyObject
property and not the actual value of the DummyWrapper
, then you'll be pointing at 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);
}
}
Upvotes: 2
Reputation: 7446
The ref
keyword won't give you this capability. Instead, it allows you to re-assign the passed variable to a new instance, but only within the context of the 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're storing the object reference as a field, which has entirely different semantics - reassigning that field is different from reassigning the original variable.
To keep the data synchronized, either operate on the same instance when you make your changes (e.g., this.dummyObject.Name = "I am changed";
) instead of creating an entirely new instance, or you'll need to come up with a mechanism for propagating those changes between forms (e.g., have your forms implement INotifyPropertyChanged
and subscribe to each other's property change notifications).
Upvotes: 0
Reputation: 34177
I think you've misunderstood what the ref keyord does. When you pass the dummyObject into the constructor of Form2, Form2 does not link it's own dummyObject field with the dummyObject field in Form1.
You can keep the data synchronised by avoiding creating new instances of DummyObject or by making Form1 tell Form2 whenever it does create a new instance.
As it stands, you don't actually need to use the ref keyword at all, it won't make any difference if you were to remove it.
Upvotes: 4