通过引用传递此内容(参考此)
本文关键字:参考 引用 | 更新日期: 2023-09-27 18:32:02
请考虑以下代码片段(在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
对象的地址复制到myRef
;所以myRef
变量与this
无关,除了它们都指向同一个对象。
它按预期工作。问题是这与您所期望的不一样。
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
)。
使用 myRef
确实有效,在方法调用之后,它实际上是对新 Form 实例的引用。它还将更改 Text
属性,但您不会看到任何内容,因为您没有显示新的 Form 实例。它与原始表单(this
)不同,因此该表单不会以任何方式更改。
如果要更改窗体的属性,可以这样做:
public void Change(Form1 theRef)
{
theRef.Text = "I am a new form";
}
可以这样称呼:
Change(this);
但是您不能像这样创建一个"新表单"来替换现有表单。也许您应该考虑使用某种Reset()
功能,根据需要清除表单。
如果您确实需要替换当前表单,那么您将需要某种可以管理原始表单的"父级"。
因为您无法为this
赋值。
实际上它有效。我假设您希望您当前的形式发生变化,但这不会像这样工作。代码的作用是更改传递的引用的内容。它不会破坏/替换您当前的表单。
你需要做的是这样的
- 创建(新)表单并打开它 (.显示或 。显示对话框)
- 销毁当前表单 (.关闭)
在引用类型中,this
是只读的,因此无法解决此问题。
您的第二次调用确实有效,但它会更改myRef
变量以引用新形式。 this
仍然引用原始形式,因为无论如何您都无法更改它。
这个答案只是对上面评论的更完整的回应,以澄清this
在 C#/.NET 中并不是只读的。
在值类型中,您可以为this
赋值,但仍然无法通过引用传递this
,因此您的代码仍然不起作用。
但是,下面是一个将新值分配给 this
的 LINQPad 示例,该值在值类型中"有效"。
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。
但是,这仅适用于值类型。它不适用于引用类型,您也不能通过引用传递。