考虑以下代码片段(用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
无关,只是它们都指向同一个对象。
答案 0 :(得分:7)
它可以正常工作。问题是这与你期望的不一样。
Form1 myRef = this;
var b1 = object.ReferenceEquals(myRef, this); // true
Change(ref myRef);
var b2 = object.ReferenceEquals(myRef, this); // false
因此myRef
的值会发生变化。应该预期变化不会传播到this
;在完成作业myRef
和this
之后是完全独立的变量。 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)
实际上它有效。我假设您希望您当前的表单发生变化,但这不会像这样工作。您的代码所做的是更改您传递的引用的内容。它不会破坏/替换您当前的表单。
你需要做的是像
答案 4 :(得分:0)
在参考类型中,this
是只读的,没有办法解决这个问题。
您的第二次通话确实有效,但它会更改myRef
变量以引用新表单。 this
仍然指原始形式,因为无论如何你都无法改变它。
这个答案只是对上述评论的更完整回复,以澄清this
在C#/。NET 中的任何地方都不是只读。
在值类型中,您可以为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。
然而, 仅适用于值类型。它不适用于引用类型,也不能通过引用传递。