Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to Lock() within a Closure? What does that look like in Lambdas and code output?

I was reading this question, and read this response

This is actually a fantastic feature. This lets you have a closure that accesses something normally hidden, say, a private class variable, and let it manipulate it in a controlled way as a response to something like an event.

You can simulate what you want quite easily by creating a local copy of the variable, and using that.

Would we need to implement Lock() in this situation?

What would that look like?

According to Eric Lippert a compiler makes code look like this:

private class Locals
{
  public int count;
  public void Anonymous()
  {
    this.count++;
  }
}

public Action Counter()
{
  Locals locals = new Locals();
  locals.count = 0;
  Action counter = new Action(locals.Anonymous);
  return counter;
}

What does the Lambda would look like, as well as the long-form code?

like image 350
TLDR Avatar asked Oct 18 '25 12:10

TLDR


1 Answers

If you have a reason to lock, then yes, there's nothing stopping you from putting a lock statement in a closure.

For example, you could do this:

public static Action<T> GetLockedAdd<T>(IList<T> list)
{
    var lockObj = new object();
    return x =>
    {
        lock (lockObj)
        {
            list.Add(x);
        }
    }
}

What does this look like, in terms of compiler-generated code? Ask yourself: what is captured?

  • A local object used for locking.
  • The IList<T> passed in.

These will be captured as instance fields in a compiler-generated class. So the result will look something like this:

class LockedAdder<T>
{
    // This field serves the role of the lockObj variable; it will be
    // initialized when the type is instantiated.
    public object LockObj = new object();

    // This field serves as the list parameter; it will be set within
    // the method.
    public IList<T> List;

    // This is the method for the lambda.
    public void Add(T x)
    {
        lock (LockObj)
        {
            List.Add(x);
        }
    }
}

public static Action<T> GetLockedAdd<T>(IList<T> list)
{
    // Initializing the lockObj variable becomes equivalent to
    // instantiating the generated class.
    var lockedAdder = new LockedAdder<T> { List = list };

    // The lambda becomes a method call on the instance we have
    // just made.
    return new Action<T>(lockedAdder.Add);
}

Does that make sense?

like image 154
Dan Tao Avatar answered Oct 21 '25 00:10

Dan Tao