在两个窗体之间通过引用传递参数

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窗体。现在,我希望通过传递参数时使用'ref'关键字,使得Form1中的变量i也具有值2,但实际上其值仍为1。我做错了什么?为什么在我的示例中'ref'关键字不起作用?

谢谢。

8个回答

6
“ref”修饰符只在构造函数调用期间起作用。它仅与该“参数”相关联……在构造函数完成后,该参数就不存在了。
当您执行赋值操作时:
i = x;

那只是复制了“值”。它没有以任何其他方式将变量i与x相关联。
一般的经验法则是:如果你在方法/构造函数中不改变参数的值(在你的例子中确实如此),那么ref修饰符什么也没做。
你不能做你想做的事情:你不能让一个字段(在这种情况下是Form2.i)成为某个其他变量的别名。

我想补充一下,Form2已经公开了一个public int i,所以他应该:从构造函数中删除参数,使用f2.i = i设置字段;在ShowDialog()之后使用i = f2.il读取它。 - configurator
1
我真的希望真正的代码中没有公共字段...并且该类也不叫Form2 :) - Jon Skeet

6

实际发生的情况:

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

有很多方法可以实现你想要的功能,可以使用事件,也可以通过传递一个在对象1和对象2之间共享的对象来实现。

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

这可能是实现你想要的最简单的方法。

我之前认为如果使用ref关键字传递整数,那么这和传递对象是一样的。谢谢你澄清了这个问题,现在它可以工作了。 - sventevit
你也可以传递一个表单引用/实例,而不是对象。 - Jan

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;
  }
}

记住,在所有这些中要注意内存管理。


2
如果您真的想从Form2中设置Form1变量,可以使用回调方法(即传递设置Form1变量并在Form2中运行它的方法地址)。
类似于这样:
```` void SetVariable(Action setVariable) { setVariable("your value"); } ````
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上设置一个公共属性。

0
i = x;

这个语句将 i 的值复制到 x 的值。如果要更改 x 的值,您需要在构造函数中实际分配一个值给它。例如:

x=2;

0

ref关键字的作用范围仅限于声明方法:Form2构造函数。一旦该方法退出,form1中的i和form2中的i不再相互关联(特别是因为它们是值类型)。


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

如何从Form2返回值到Form1? - sventevit

0

感谢您的回答...

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

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

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

谢谢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接