views:

201

answers:

4

Is there a way to force the this keyword to act as a ref argument? I would like to pass in a visitor that modifies multiple properties on the object, but this only wants to act like a value parameter.

Code in Object:

public void Accept(Visitor<MyObject> visitor)
{
    visitor.Visit(this);
}

Code in Visitor:

public void Visit(ref Visitor<MyObject> receiver)
{
    receiver.Property = new PropertyValue();
    receiver.Property2 = new PropertyValue();
}
+9  A: 

Since you are not actually changing what receiver refers to there is no need for the ref keyword. However, if that would have been the case, you would not be able to make this refer to another instance.

In order to pass this as a ref parameter, you would need to write it like this:

Visit(ref this);

That code will not compile: "Cannot pass '<this>' as a ref or out argument because it is read-only"

Fredrik Mörk
Yes, you are exactly right. But I want the original class to retain the changes made by the Visitor. If I don't pass as ref, then won't I only modify the properties of a *copy* of <this>?
grefly
@grefly: Not if "this" is a class. Provided you don't "visit" custom struct (value types), ref isn't required.
Reed Copsey
Thank you, you are exactly right!
grefly
+3  A: 

If your Visitor<T> is a class, then you don't need the ref keyword.

All the info inside a class is automatically changed if they are changed in a method

Ngu Soon Hui
This is correct - I'm sorry I can't mark both as Answers.
grefly
A: 

Do you really need the ref keyword ?

ref would be useful if you change receiver instance e.g. receiver = null;

otherwise

receiver.Property is accessible also without ref keyword

digEmAll
+1  A: 

It sounds like you got an answer to your larger question already. But let's consider this one anyway.

Is there a way to force the this keyword to act as a ref argument?

Yes. Work it through logically.

  • A ref argument makes an alias for a variable.
  • "this" is not a variable in a reference type
  • "this" is a variable in a value type
  • therefore the only way to pass a "ref this" is from an instance method of a value type.

And in fact that is how "this" is implemented in a value type behind the scenes. When you have a (worst practice! do not actually do this) mutable value type:

struct S
{
    private int x;
    public void M()
    {
        this.x = 123;
    }
}
...
S s = new S();
s.M();

Since instances of S are passed by value how is it that M mutates s? s must be passed by reference! In fact the code we generate is just as if you'd written something like:

struct S
{
    private int x;
    public static void M(ref S THIS)
    {
        THIS.x = 123;
    }
}
...
S s = new S();
S.M(ref s);

In short, a "this" in a struct already is passed as a ref parameter, so there is no problem passing it along again. Doing so is almost always a terrible idea but it is legal.

Eric Lippert