【问题标题】:Result of Passing WinForm by Reference and Value通过引用和值传递 WinForm 的结果
【发布时间】:2014-03-04 16:34:12
【问题描述】:

我有一个名为 Form1 的 win 表单窗口,其中 - 一个名为 Label1 的标签, 两个按钮分别命名为 button1 和 button2。

当我点击 button1 时,它会创建一个名为 f 的 Form1 类型的新窗口, 初始化为当前窗口,即this(Form1), f 是发送到一个名为 ChangeByReference 的方法作为参考。

ChangeByReference 方法更改表单的文本、Label1 的文本和前景色,即 通过引用传递

当我点击 button2 时,这个实例方法名为 ChangeByValue 作为值。

ChangeByValue 方法创建一个新窗口,初始化为 Form1 的默认构造函数, 然后将其设置为参数 valForm,我更改了一些属性并最终使用 显示方法。

现在的问题是为什么 ChangeByValue 方法调用会破坏原始窗口 并显示新表单,因为它的参数是按值传递的?

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
        this.Text = "Original Window";
    }

    public void ChangeByReference(ref Form1 refForm)
    {
        Form1 f = refForm;
        f.label1.Text = "This is changed by Reference";
        f.label1.ForeColor = Color.Aquamarine;
    }

    public void ChangeByValue(Form1 valForm)
    {
        Form1 f = new Form1();
        f =  valForm;
        f.Text = "Changed Window";
        f.label1.Text = "This is changed by Value";
        f.label1.ForeColor = Color.Red;
        f.Show();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form1 f = this as Form1;
        ChangeByReference(ref f);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        ChangeByValue(this);
    }

}

【问题讨论】:

    标签: c# winforms data-structures


    【解决方案1】:

    方法ChangeByReference 并不需要ref。您没有使用ref 的“功能”。我认为您混合了两个概念,一个是“引用类型”,第二个是“将参数作为引用传递”。同样根据文档:

    不要将引用传递的概念与引用类型的概念混淆。这两个概念并不相同。方法参数无论是值类型还是引用类型,都可以通过 ref 进行修改。值类型在通过引用传递时没有装箱。

    来源:MSDN - ref (C# Reference)

    在您的代码中,您只需更改作为参数传递的表单的一些属性。参数指定为ref与否,效果相同。

    在您的第二种方法ChangeByValue 中,您首先初始化一个新的Form1 对象,但在您将局部变量重新分配给参数值之后。这样,新对象将不再被使用(您将其“扔掉”)。所以接下来的代码行,您实际上是在更改/设置您通过参数提供的表单的属性。在这种情况下(来自button2_Click 事件),您正在更改当前表单。

    一篇有趣的文章:Parameter passing in C#(作者 Jon Skeet)。

    【讨论】:

    • 那我应该写什么,以便从 ChangeByValue 方法中生成另一个窗口
    • @RAZER 只需删除第二行 (f = valForm;),它将生成一个新表单。如果您想生成当前窗口的“副本”,则必须“克隆”当前表单。
    • 只需从您的方法中删除第二行。
    • 你建议我如何克隆它?
    • 将新对象的属性设置为当前表单的属性值。有很多方法可以克隆对象。
    【解决方案2】:

    按值传递valForm 参数意味着更改valForm 的引用不会更改传递变量的引用(在您的示例中为this)。

    在您的方法中,您为f 分配了一个与valForm 引用完全相同的对象的引用,这意味着两个变量都指向同一个对象,即this。如果您通过一个引用修改该对象,它会反映在另一个引用中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 2014-09-14
      • 2015-11-14
      • 1970-01-01
      • 2013-06-04
      • 1970-01-01
      相关资源
      最近更新 更多