简体   繁体   中英

Passing this by reference (ref this)

Consider the following code snippet( written in a Windows Form Application):

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";
    }
}

Passing this by reference is not allowd. That's ok and sensible. But why passing this indirectly as shown above is not working? As I know if a parameter is passed by reference any assignment in the called method is reflected out to the caller method. Why isn't it working here?

Update to make the question clear

1- I am not struggling to accomplish anything special. I am just trying to test ref .

2- The reason why I misunderstood the ref is that I totally forgot Form1 myRef = this actually copies the address of underlying Form1 object to myRef ; so myRef variable has nothing to do with this except that both of them points to the same object.

It works as it should. The problem is that this is not the same as what you are expecting.

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

So the value of myRef changes. That the change does not propagate to this should be expected; after making the assignment myRef and this are totally separate variables. C# does not have "ref variables", so it couldn't be any other way (even if it had, reassigning this in this manner would never be allowed).

Using myRef does actually work, after the method call it will in fact be a reference to a new Form instance. It will also have the Text property changed, but you will not see anything because you are not displaying your new Form instance. It is not the same instance as your original form ( this ), so that form will not be changed in any way.

If you want to change a property of the form you can do it like this:

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

which can be called like so:

Change(this);

But you cannot create a "new form" to replace the existing one like that. Perhaps you should consider having some sort of Reset() function, that clears the form as you need.

If you really need to replace the current form, then you will need some sort of "parent" that can manage the original form.

因为您无法this分配值。

Actually it works. I assume you expect your current form to change, this however won't work like this. What your code does is changing the content of the reference you pass. It does not destroy/replace your current form.

What you need to do is something like

  • Create (new) a Form and Open it (.Show or .ShowDialog)
  • Destroy the current Form (.Close)

In reference types, this is read-only, there's no way around that.

Your second call does indeed work, but it changes the myRef variable to refer to a new form. this still refers to the original form, since you cannot change that anyway.

This answer is just a more full response to a comment above, to clarify that this is not read-only everywhere in C#/.NET .

In a value type, you can assign a new value to this , but you still cannot pass this by reference, so your code still won't work.

However, here's a LINQPad example of assigning a new value to this , which "works" in a value type.

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);
    }
}

Notice that the Value field is read-only, so there appears to be no way that the field should change its value, however the output of the above program is that first the field has the value 17, the next time we check it it has the value 42.

This, however, only works in value types. It does not work with reference types, and you cannot pass by reference either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM