views:

299

answers:

3

How Do I capture a variable?
Alternatively, can I store a reference to an object reference?

Normally, a method can alter a variable outside of it using ref keyword.

void Foo(ref int x)
{
    x = 5;
}

void Bar()
{
    int m = 0;
    Foo(ref m);
}

This is clear and straight-forward.

Now let's consider a class to achieve the same thing:

class Job
{
    // ref int _VarOutsideOfClass; // ?????

    public void Execute()
    {
        // _VarOutsideOfClass = 5; // ?????
    }
}

void Bar()
{
    int m = 0;
    var job = new Job()
    {
        _VarOutsideOfClass = ref m    // How ?
    };
    job.Execute();
}

How do I write it correctly ?


Comments: I can't make it a method with an ref argument, because typically Execute() will called somewhat later in a different thread, when it comes up in the queue.

Currently, I made a prototype with plenty of lambdas:

class Job
{
    public Func<int> InParameter;
    public Action<int> OnResult;

    public void Execute()
    {
        int x = InParameter();
        OnResult(5);
    }
}

void Bar()
{
    int m = 0;
    var job = new Job()
    {
        InParameter = () => m,
        OnResult = (res) => m = res
    };
    job.Execute();
}

... but maybe there is a better idea.

A: 

Use Array with 1 element

class Job{
int[] _VarOutsideOfClass = new int[1];

Also You can use wrapper "int?" - forgive them nullable, but remember that it always passed over reference.

Dewfy
no it is not. Nullable<T> is a struct
AZ
yep, forgive Nullable! But array is still good reference holder.
Dewfy
+1  A: 

You can't have a ref field. See, for example, http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx (scroll down to where it says "This explains why you cannot make a “ref int” field....").

A lambda or a delegate is probably your best bet here. I suppose you could use an event, or an observer interface, or something.

Roger Lipscombe
A: 

Here's a guess (I haven't tried/tested it):

class Job
{
  Action<int> m_delegate;

  public Job(ref int x)
  {
    m_delegate = delegate(int newValue)
    {
      x = newValue;
    };
  }

  public void Execute()
  {
    //set the passed-in varaible to 5, via the anonymous delegate
    m_delegate(5);
  }
}


If the above doesn't work, then say that the Job constructor takes a delegate as its parameter, and construct the delegate inside the Bar class (and pass the delegate instead of passing the ref parameter).

ChrisW
Error: Cannot use ref or out parameter 'x' inside an anonymous method, lambda expression, or query expression
Roger Lipscombe
Yep, doesn't work.
modosansreves