2

考虑以下代码片段(在 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实际上将底层对象的地址复制到;所以变量与它们无关,只是它们都指向同一个对象。Form1myRefmyRefthis

4

5 回答 5

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# 没有“引用变量”,所以它不可能有任何其他方式(即使有,this也绝不允许以这种方式重新分配)。

于 2013-09-20T09:38:00.727 回答
3

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

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

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

可以这样调用:

Change(this);

但是你不能创建一个“新表单”来替换现有的那样。也许您应该考虑使用某种Reset()功能,根据需要清除表单。

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

于 2013-09-20T09:32:42.587 回答
1

因为您无法为this.

于 2013-09-20T09:33:12.477 回答
1

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

你需要做的是类似

  • 创建(新)表单并打开它(.Show 或 .ShowDialog)
  • 销毁当前表单 (.Close)
于 2013-09-20T09:37:43.703 回答
0

在引用类型中,this是只读的,没有办法解决。

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

这个答案只是对上面评论的更完整的回应,以澄清在 C#/.NET 中this并非所有地方都是只读的。

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

但是,这是一个LINQPad示例,它为 分配一个新值this,它在值类型中“工作”。

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。

但是,这适用于值类型。它不适用于引用类型,也不能通过引用传递。

于 2013-09-20T09:42:56.473 回答