我有一种困惑,当我在另一个类的构造函数中通过引用传递变量时,在通过refrence传递该对象之后,我使用new关键字重新创建了refrence对象。
现在我传递refrenced对象的类不会反映更新的数据。 上述问题的一个例子如下所示:
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);
}
}
当我在表单1中重新设置对象并在表单2中显示其值时,它仍显示“我已更改”而不是“我被改变”。
如何保持数据同步?
答案 0 :(得分:4)
我认为你误解了ref keyord的作用。当您将dummyObject传递给Form2的构造函数时,Form2不会将它自己的dummyObject字段与Form1中的dummyObject字段链接。
您可以通过避免创建DummyObject的新实例或使Form1在创建新实例时告诉Form2来保持数据同步。
就目前而言,你实际上根本不需要使用ref关键字,如果要删除它,它将没有任何区别。
答案 1 :(得分:2)
您不能以这种方式保持变量同步;没有ref
实例或静态变量的概念,只有ref
个参数。 dummyObject
实例变量确实(并且将始终)表示不同的内存槽。您所做的只是将DummyObject
参数中的值复制到dummyObject
;你所做的一切都不会受到参数是否被声明为ref
的影响。
典型的方法是将dummyObject
的值公开为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
}
}
但这意味着您需要保留Form2
的实例,以便更改属性的值。
另一个选项,虽然有点复杂,但会传递一个包含该属性的包装类,而不是将其添加到表单中。
public class DummyWrapper
{
public DummyObject DummyObject { get; set; }
}
然后,您更改表单以使用DummyWrapper
而不是DummyObject
,然后在您想要获取或设置值时访问dummyWrapper.DummyObject
属性。只要您只更改DummyWrapper.DummyObject
属性的值而不是DummyWrapper
的实际值,那么您将指向同一个实例。
例如:
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 :(得分:2)
你误解了“ref”的作用。我必须解释“ref”的最佳方法是为变量创建别名。当你说
void M(ref int x)
{
Console.WriteLine(x);
x = 10;
}
...
int y = 123;
M(ref y);
你在电话网站上说的是“x现在是变量y的另一个名字”。也就是说,这就像你简单地说
一样int y = 123;
Console.WriteLine(y);
y = 10;
x是y的别名。不幸的是,我们选择“ref”这个词来表示“为一个变量做一个别名”,因为这很令人困惑,但这就是语言设计者所选择的。
现在,如果你说
void N(int z)
{
Console.WriteLine(z);
z = 10;
}
...
int y = 123;
N(y);
不会使z成为y的别名。该代码与
相同int y = 123;
int z = y;
Console.WriteLine(z);
z = 10;
不会改变y的值,因为z和y是两个不同的变量,而x和y是相同变量的两个不同名称。
答案 3 :(得分:0)
ref
关键字不会为您提供此功能。相反,它允许您将传递的变量重新分配给新实例,但仅限于方法的上下文中。澄清:
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";
}
但是,在您的情况下,您将对象引用存储为具有完全不同语义的字段 - 重新分配该字段与重新分配原始变量不同。
要保持数据同步,请在进行更改时对同一实例进行操作(例如this.dummyObject.Name = "I am changed";
),而不是创建一个全新的实例,或者您需要提供一种传播机制表单之间的更改(例如,让表单实现INotifyPropertyChanged
并订阅彼此的属性更改通知)。
答案 4 :(得分:0)
它不能做你想要的是Form1.button3_click的第一行,创建第二个DummyObject实例。此新实例永远不会发送到Form2,因此Form2只有旧实例的副本。现在Form1和Form2有不同的对象,因此有不同的消息。
只有当Form2的构造函数想要在OUT路径上为参数分配新实例时,才会在您的示例中使用ref关键字(它与out参数不同,因为它是双向的而不是一个 - 办法)。这样的赋值会改变Form1.dummyObject字段的值。
答案 5 :(得分:0)
我已使用Adam Robinson建议的属性重新考虑我的应用程序以进行同步。现在我的代码已经如下所示进行了更改并产生了所需的结果。
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.";
}
}
感谢每个人的快速反应。