How to save a ref variable for later use?

2019-01-26 05:08发布

So this works..

public MyClass(ref Apple apple)
{
    apple = new Apple("Macintosh"); // Works fine
}

But is it possible to do something like this?

private Apple myApple;

public MyClass(ref Apple apple)
{
    myApple = apple;
}

public void ModifyApple()
{
    myApple = new Apple("Macintosh"); // does not change the input variable like the first example did
}

When the ref variable is copied to the member variable myApple it appears to lose it's 'ref-ness' and re-assigning it no longer changes the input variable. Is there a way around this?

标签: c# reference ref
4条回答
相关推荐>>
2楼-- · 2019-01-26 05:19

ref-ness is a property of parameters of functions and arguments you are passing to functions. It's not a property of variables (or even fields) in general.

So indeed, what you are trying there is doomed from the start.

查看更多
别忘想泡老子
3楼-- · 2019-01-26 05:22

Why not just have ModifyApple return the modified Apple instance?

public Apple ModifyApple()
{
    myApple = new Apple("Macintosh"); // does not change the input variable like the first example did
    return myApple;
}
查看更多
再贱就再见
4楼-- · 2019-01-26 05:30

No, there isn't. myApple is a field that holds a reference to an Apple; the parameter apple, however, is actually a reference-to-a-reference-to-an-Apple. When you assign apple to myApple you dereference the value of the parameter. Beyond that, they are separate and distinct.

So no: it is not possible.

What would be possible is to have something like:

public class AppleWrapper {
    public Apple Value {get;set;}
}

Now; if you store an AppleWrapper, any number of callers can access and change the .Value

查看更多
5楼-- · 2019-01-26 05:39

Not really, no. By the time your code is next invoked, the original variable used as the method argument may no longer even exist:

void Foo()
{
    MyClass x = Bar();
    x.ModifyApple();
}

MyClass Bar()
{
    Apple apple = new Apple();
    return new MyClass(ref apple);
}

Here, apple is a local variable, in a stack frame which will have been popped by the time we call ModifyApple.

Are you sure you need to modify the original caller's variable rather than just changing the object itself?

One way to sort of fake this would be to use a wrapper type to start with:

public class MutableWrapper<T>
{
    public T Value { get; set; }
}

Then pass in a MutableWrapper<Apple>, and store that in your class. Then in ModifyApple you can write:

wrapper.Value = new Apple();

This won't change the caller's variable, but next time the caller looks at the Value property, they'll see your new apple.

To be honest, this sort of thing tends to make for hard-to-maintain code, and even ref isn't great for readability. If you can explain the bigger picture of what you're trying to achieve, we may be able to suggest a better overall approach.

查看更多
登录 后发表回答