3

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

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

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

在这种情况下我们需要实现 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;
}

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

4

4 回答 4

5

如果您有理由锁定,那么是的,没有什么能阻止您将lock语句放入闭包中。

例如,您可以这样做:

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

就编译器生成的代码而言,这是什么样的?问问自己:捕获了什么?

  • 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);
}

那有意义吗?

于 2011-01-24T05:59:07.327 回答
2

对的,这是可能的。

只要确保你不改变锁定的对象实例,否则它将无用。

于 2011-01-24T05:04:34.270 回答
1

你可以有这样的功能:

static Func<int> GetIncrementer()
{
    object locker = new object();
    int i = 0;
    return () => { lock (locker) { return i++; } };
}

当您调用它时,它将返回一个以线程安全方式递增内部计数器的函数。虽然不是实现此类功能的最佳方式,但它确实演示了闭包内的锁。

于 2011-01-24T05:43:19.803 回答
0

我在互联网旅行中遇到了这个问题,我知道这是一个非常古老的问题,但我想我会提出一个替代答案。

可以在包装函数的帮助下锁定 lambda 内部,这允许相对优雅的语法。

这是辅助函数(在静态类中):

public static class Locking
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    [DebuggerNonUserCode, DebuggerStepThrough]
    public static T WithLock<T>(this object threadSync, Func<T> selector)
    {
        lock (threadSync)
        {
            return selector();
        }
    }
}

以下是你如何使用它:

private readonly object _threadSync = new object();
private int _myProperty;

public int MyProperty
    => _threadSync.WithLock(() => _myProperty);
于 2018-06-27T09:28:24.967 回答