【问题标题】:C# closures and access to external variablesC# 闭包和对外部变量的访问
【发布时间】:2012-01-02 03:33:17
【问题描述】:

我正在尝试通过调用来使用以下内容:StaticClass.DeleteObject(null, key)。它没有像我预期的那样工作,并且 lambda 表达式中的代码抛出 NullReferenceException 因为上下文为空,这是可以理解的。我尝试将 AmazonS3Operation 的上下文参数更改为 ref,但 ReSharper 然后警告“访问修改后的闭包”。

基本上我只是想在那个辅助方法中“注入” lambda 表达式,然后调用它,如果你知道我希望它如何工作的话。这可能吗,或者如果没有,我能做些什么类似的事情?

/// <exception cref="IOException"></exception>
public static void DeleteObject(this AmazonS3Context context, string key)
{
    AmazonS3Operation(context, () => context.Client.DeleteObject(
        new DeleteObjectRequest().WithBucketName(context.CurrentBucket)
            .WithKey(key)));
}

/// <exception cref="IOException"></exception>
private static void AmazonS3Operation(AmazonS3Context context, Action operation)
{
    var shouldDispose = false;
    try
    {
        if (context == null)
        {
            context = new AmazonS3Context();
            shouldDispose = true;
        }

        operation();
    }
    catch (AmazonS3Exception e)
    {
        throw new IOException(e.Message, e);
    }
    finally
    {
        if (shouldDispose)
            context.Dispose();
    }
}

【问题讨论】:

    标签: c# lambda closures


    【解决方案1】:

    我会将上下文传递给动作。将 Action 参数替换为 Action 参数。

            /// <exception cref="IOException"></exception>
        public static void DeleteObject(this AmazonS3Context context, string key)
        {
            context = null;
            AmazonS3Operation(context, ctx => ctx.Client.DeleteObject(
                new DeleteObjectRequest().WithBucketName(ctx.CurrentBucket)
                    .WithKey(key)));
        }
    
        /// <exception cref="IOException"></exception>
        private static void AmazonS3Operation(AmazonS3Context context, Action<AmazonS3Context> operation)
        {
            var shouldDispose = false;
            try
            {
                if (context == null)
                {
                    context = new AmazonS3Context();
                    shouldDispose = true;
                }
    
                operation(context);
            }
            catch (AmazonS3Exception e)
            {
                throw new IOException(e.Message, e);
            }
            finally
            {
                if (shouldDispose)
                    context.Dispose();
            }
        }
    

    【讨论】:

    • +1 我不知道谁对此投了反对票,但这是我正在考虑的确切解决方案!这是一个很好的答案。
    【解决方案2】:

    在方法中使用局部变量而不是修改你的参数:

    AmazonS3Context localContext = context;
    try {
        if (locaContext == null) {
        // keep using localContext...
    

    让你的行动成为

    Action<AmazonS3Context> 
    

    所以你可以传入实例而不是依赖闭包。被调用的方法已经有你想要的实例作为它的另一个参数,所以在这里使用闭包会被认为是有害的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-31
      • 1970-01-01
      • 1970-01-01
      • 2018-12-24
      • 2023-02-09
      • 2017-10-05
      • 2013-04-24
      • 1970-01-01
      相关资源
      最近更新 更多