C# 闭包和对外部变量的访问

Posted

技术标签:

【中文标题】C# 闭包和对外部变量的访问【英文标题】:C# closures and access to external variables 【发布时间】: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();
    

【问题讨论】:

【参考方案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> 

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

【讨论】:

以上是关于C# 闭包和对外部变量的访问的主要内容,如果未能解决你的问题,请参考以下文章

C#和 JS的闭包

前端闭包

js变量作用域和闭包的示例

js-闭包

js 闭包

js 闭包