通过引用传递此(参考此)

时间:2013-09-20 09:30:59

标签: c#

考虑以下代码片段(用Windows窗体应用程序编写):

public partial class Form1
{
    ....
    public void Caller()
    {
        Form1 myRef = this;
        Change(ref this)    //--> won't compile because *this* is read-only
        Change(ref myRef);  //--> compiles but doesn't work.
    }
    ....

    public void Change(ref Form1 theRef)
    {
        theRef = new Form1();
        theRef.Text = "I am a new form";
    }
}

不允许通过引用传递this。那是好的和明智的。但为什么如上所示间接传递this不起作用?据我所知,如果参数通过引用传递,则被调用方法中的任何赋值都会反映到调用方法中。为什么不在这里工作?

更新以使问题清晰

1-我没有努力完成任何特别的事情。我只是想测试ref

2-我误解ref的原因是我完全忘记了Form1 myRef = this实际复制基础Form1对象的地址{{1} };所以myRef变量与myRef无关,只是它们都指向同一个对象。

5 个答案:

答案 0 :(得分:7)

它可以正常工作。问题是这与你期望的不一样。

Form1 myRef = this;
var b1 = object.ReferenceEquals(myRef, this); // true
Change(ref myRef);
var b2 = object.ReferenceEquals(myRef, this); // false

因此myRef的值会发生变化。应该预期变化不会传播到this;在完成作业myRefthis之后是完全独立的变量。 C#没有“ref变量”,所以它不能是任何其他方式(即使它有,以这种方式重新分配this永远不会被允许)。

答案 1 :(得分:3)

使用myRef确实有效,在方法调用之后它实际上是对新Form实例的引用。它还会更改Text属性,但您不会看到任何内容,因为您没有显示新的Form实例。 与原始表单(this)的实例相同,因此不会以任何方式更改该表单。

如果要更改表单的属性,可以这样做:

public void Change(Form1 theRef)
{
    theRef.Text = "I am a new form";
}

可以像这样调用:

Change(this);

但你无法创建一个“新形式”来取代现有的那种形式。也许您应该考虑使用某种Reset()函数,根据需要清除表单。

如果您确实需要替换当前表单,那么您将需要某种可以管理原始表单的“父级”。

答案 2 :(得分:1)

因为您无法为this分配值。

答案 3 :(得分:1)

实际上它有效。我假设您希望您当前的表单发生变化,但这不会像这样工作。您的代码所做的是更改您传递的引用的内容。它不会破坏/替换您当前的表单。

你需要做的是像

  • 创建(新)表单并打开它(.Show或.ShowDialog)
  • 销毁当前表格(.Close)

答案 4 :(得分:0)

在参考类型中,this是只读的,没有办法解决这个问题。

您的第二次通话确实有效,但它会更改myRef变量以引用新表单。 this仍然指原始形式,因为无论如何你都无法改变它。

这个答案只是对上述评论的更完整回复,以澄清this在C#/。NET 中的任何地方都不是只读

在值类型中,您可以为this分配新值,但仍然无法通过引用传递this,因此您的代码仍无效。

但是,这是LINQPadthis分配新值的示例,该值在值类型中“有效”。

void Main()
{
    Test t = new Test(17);
    t.Dump();
    t.StrangeMutation();
    t.Dump();
}

public struct Test
{
    public readonly int Value;

    public Test(int value)
    {
        Value = value;
    }

    public void StrangeMutation()
    {
        this = new Test(42);
    }
}

请注意,Value字段是只读的,因此字段似乎无法更改其值,但上述程序的输出首先是字段的值为17,下次我们检查它时它的值是42。

然而, 仅适用于值类型。它不适用于引用类型,也不能通过引用传递。