C#闭包和访问外部变量

时间:2012-01-02 03:33:18

标签: c# lambda closures

我正在尝试通过调用StaticClass.DeleteObject(null, key)来使用以下内容。它没有按照我的预期工作,并且lambda表达式中的代码抛出NullReferenceException,因为context是null,这是可以理解的。我尝试将AmazonS3Operation的context参数更改为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();
    }
}

2 个答案:

答案 0 :(得分:3)

我会将上下文传递给动作。将Action参数替换为Action&lt; AmazonS3Context&gt;参数。

        /// <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 :(得分:1)

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

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

让你的行动

Action<AmazonS3Context> 

所以你可以传入实例而不是依赖于闭包。被调用的方法已经将您想要的实例作为其他参数,因此在此处使用闭包将被视为有害。

相关问题