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

C# 在两个窗体之间通过引用传递参数,c#,pass-by-reference,C#,Pass By Reference,我有两张表格(表格一和表格二)。在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; } public partial cl

我有两张表格(表格一和表格二)。在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;
}
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();
    }
}
然后我将Form2上的变量I设置为值2,并关闭Form2。现在我希望Form1上的变量I的值为2(因为通过传递参数得到'ref'关键字),但值仍然为1。我做错了什么?为什么ref关键字在我的示例中不起作用

谢谢

在构造函数调用过程中,“ref”修饰符只会起到任何作用。它只与该参数关联。。。构造函数完成后,该参数不再存在

执行任务时:

i = x;
这只是复制值。它不会以任何其他方式将变量
i
x
关联

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

你不能做你想做的事情:你不能让一个字段(在本例中是Form2.
i
)成为其他变量的别名

i = x;
此语句正在将i的值复制到x的值。要更改x,您需要在构造函数中实际为其赋值。例如

x=2;

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

实际发生的情况

  • 您创建了一个名为“i”的整数成员的object1
  • 将对“i”的引用传递到新的对象构造函数中。对“i”的引用称为“x”
  • 将“x”的值复制到第二个对象(也称为“i”)中的变量中
  • 退出object2的构造函数。对object1.i的引用到此结束
  • 您可以修改object2.i(它是object1.i的副本,但不是引用、指针或链接)。object1.i未被修改
  • 有许多方法可以实现您想要的,或者通过事件,或者通过传入将在object1和object2之间共享的对象

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

    这可能是实现目标的最简单的方法。

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

    我同意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;
      }
    }
    
    记住记住所有这些都需要内存管理。

    谢谢您的回答

    目前,我发现了三种方法可以将变量从Form2返回到Form1:

    • 在窗体之间传递对象,而不是普通整数
    • 在Form1中,我可以使用get和set方法放置“private int myVariable”和属性“public int myVariable”。然后我可以将整个Form1传递给Form2的构造函数,在那里我可以访问Form1.MyVariable属性
    • 指针
    还有其他选择吗?这三个选项中哪一个更好?(在我的示例中,我只需要从Form2访问Form1中的一个整数)


    谢谢

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

    大概是这样的:

    public int i;
    public Form2(ref int x)
    {
        InitializeComponent();
        i = x;
    }
    
    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上设置一个公共属性。

    我认为如果使用ref关键字传递integer,它与传递对象是一样的。谢谢你澄清了这一点,它现在可以工作了。你也可以传递一个表单引用/实例,而不是对象I。我如何才能将值从Form2返回到Form1?我想补充一点,Form2已经公开了一个公共int I,所以他应该:从构造函数中删除参数,将字段设置为f2.I=I;在ShowDialog()之后,用i=f2读回它。不过我真的希望真正的代码没有公共字段。。。而且这个类也不是真正的Form2:)