可以在闭包内锁定()吗?在Lambdas和代码输出中看起来像什么?

TLD*_*LDR 3 c# events closures private-members

我正在阅读这个问题,并阅读此回复

这实际上是一个很棒的功能.这允许你有一个闭包来访问通常隐藏的东西,比如私有类变量,并让它以受控的方式操作它作为对事件之类的响应.

您可以通过创建变量的本地副本并使用它来轻松模拟您想要的内容.

我们需要在这种情况下实现Lock()吗?

那会是什么样的?

根据Eric Lippert的说法,编译器使代码看起来像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)

Lambda会是什么样子,以及长格式代码?

Dan*_*Tao 5

如果你一个理由来锁定,那么是的,没有什么东西把一个阻止你lock声明封闭.

例如,您可以这样做:

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

在编译器生成的代码方面,这看起来如何?问问自己:抓到了什么?

  • object用于锁定的本地.
  • IList<T>传入.

这些将作为编译器生成的类中的实例字段捕获.所以结果看起来像这样:

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);
}
Run Code Online (Sandbox Code Playgroud)

那有意义吗?