3

我有两种形式(Form1 和 Form2)。在 Form1 上有一个“public int i”变量,它在 Form1 构造函数中设置为值 1。然后我使用以下代码从 Form1 打开 Form2:

Form2 f2 = new Form2(ref i);
f2.ShowDialog();

Form2 的构造函数如下所示:

public int i;
public Form2(ref int x)
{
    InitializeComponent();
    i = x;
}

然后我将 Form2 上的变量 i 设置为值 2 并关闭 Form2。现在我希望 Form1 上的变量 i 具有值 2(因为通过传递参数的 'ref' 关键字),但值仍然是 1。我做错了什么,为什么 ref 关键字在我的示例中不起作用?

谢谢

4

8 回答 8

6

实际发生了什么。

  1. 您使用名为“i”的整数成员创建一个 object1
  2. 您将对“i”的引用传递给新的对象构造函数。对“i”的引用称为“x”。
  3. 您将“x”的值复制到第二个对象中的一个变量中,也称为“i”。
  4. 您退出 object2 的构造函数。对 object1.i 的引用到此结束。
  5. 您修改 object2.i(它是 object1.i 的副本,但不是引用、指针或链接)。object1.i 未修改。

有很多方法可以完成您想要的事情,或者使用事件,或者通过传入将在 object1 和 object2 之间共享的对象。

Class Form1
{
    Object i = new Object();
    ...
    public void DoSomething()
    {
        Form2 f = new Form2(i);
        f.Show();
    }
}

这可能是完成你想要的最简单的方法。

于 2009-09-21T12:44:32.030 回答
6

“ref”修饰符仅在构造函数调用本身期间产生任何影响。它仅与该参数相关联......并且在构造函数完成后,该参数不再存在。

执行任务时:

i = x;

那只是复制value。它没有以任何其他方式将变量i与相关联。x

作为一般经验法则:如果您不更改方法/构造函数中的参数值(在您的示例中没有更改),则ref修饰符不会做任何事情。

你不能做你想做的事:你不能让一个字段(在这种情况下是 Form2. i)成为其他变量的别名。

于 2009-09-21T12:37:40.060 回答
2

如果您真的希望能够在 Form2 中设置 Form1 中的变量,则可以使用回调方法。(即传入设置 Form1 变量并从 Form2 运行它的方法的地址)

像这样的东西:

public partial class Form1 : Form
{
    public delegate void FormReturn(string s);
    private string var1;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var frm = new Form2(ReturnFunc);
        frm.ShowDialog();
    }

    protected void ReturnFunc(string text)
    {
        var1 = text;
    }
}

public partial class Form2 : Form
{
    private Form1.FormReturn returnFunc;

    public Form2(Form1.FormReturn del)
    {
        InitializeComponent();
        returnFunc = del;
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        returnFunc.Invoke(txtText.Text);
        Close();
    }
}

虽然主要矫枉过正。您可以在 form1 上设置一个公共属性。

于 2009-09-21T16:08:18.387 回答
2

我同意 Martin 的观点,即这种类型的解决方案会增加不必要的耦合,但如果您仍然坚持将其捆绑成这样,我认为使用简单的指针就可以了。

class Form1 {  
  public int i;
  public void doSomething(){
    Form2 f = new Form2(&i);
    f.showDialog();
  }
}

然后在 Form2 中,您只需使用该指针即可。

class Form2 {
  public int *i;
  public Form2(int *r){
    InitializeComponent();
    i = r;
  }
  public void setI(int v){
    *i = v;
  }
  public int getI(){
    return *i;
  }
}

记住要记住所有这些的内存管理。

于 2009-09-21T13:50:19.710 回答
0

我不知道您这样做背后的原因,但我怀疑从对话框表单返回一个值并使用它在调用类中设置变量会更好。否则,您将在表单中添加不必要的耦合。

于 2009-09-21T12:49:15.310 回答
0

感谢您的回答...

目前,我找到了三种将变量从 Form2 取回 Form1 的方法:

  • 而不是普通的整数,在表单之间传递一个对象
  • 在 Form1 中,我可以使用 get 和 set 方法放置“private int myVariable”和“public int MyVariable”属性。然后我可以将整个 Form1 传递给 Form2 的构造函数,在那里我可以访问 Form1.MyVariable 属性
  • 指针

还有其他选择吗?这三个选项哪个更好?(在我的示例中,我只需要从 Form2 访问 Form1 中的一个整数)

谢谢

于 2009-09-21T13:52:19.893 回答
0
i = x;

该语句将 i 的值复制到 x 的值。要更改 x 您需要在构造函数中实际为其分配一个值。例如。

x=2;
于 2009-09-21T12:39:21.657 回答
0

ref keyword范围仅在声明方法内:Form2 构造函数。一旦该方法退出,form1 中的 i 和 form2 中的 i 不再链接(特别是因为它们属于 ValueType)

于 2009-09-21T12:41:02.263 回答