微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否存在通过传递回调参数传递状态或通过闭包捕获状态的技术原因?

如何解决是否存在通过传递回调参数传递状态或通过闭包捕获状态的技术原因?

昨晚在审查代码时,我发现了这段代码。值得注意的是,state 是通过执行泛型类型回调操作的 lambda 捕获的。

public static void Post<TState>(TState state,Action<TState> callback){

    if(SynchronizationContext.Current is SynchronizationContext currentContext)
        // Use capture-semantics for state
        currentContext.Post(_ => callback(state),null);
    else{
        callback(state);
    }
}

Post 但是,原生支持 state 的 pass-thru,所以上面也可以这样重写...

public static void Post<TState>(TState state,Action<TState> callback){

    if(SynchronizationContext.Current is SynchronizationContext currentContext)
        // Use pass-thru state,not 'capture'
        currentContext.Post(passedBackState => callback((TState)passedBackState),state);
    else{
        callback(state);
    }
}

我的问题很简单......在这个特定用例中,回调定义在与需要传递给它的状态相同的范围内,是否有任何技术 使用捕获语义(第一个)而不是传递(第二个)的好处和/或缺点?我个人喜欢第一个,因为只有一个变量,但我问的是技术差异,如果两者似乎都有效。

解决方法

闭包在堆上分配一个需要被垃圾回收的新对象。通过 state 参数传递数据不会分配(除非数据是需要装箱的值类型)。

这些分配可能会增加常用方法或长寿命进程(如 Web 应用程序),从而导致 CPU 周期浪费用于垃圾处理和延迟。积极删除此类分配是 .NET Core 比 .NET Old 快得多的原因之一。

Roslyn Heap Allocation Analyzer 这样的 Roslyn 分析器突出显示了这样的隐式分配,例如装箱值类型、闭包、使用 params 数组等。

更新

Rider 的 Dynamic Program Analysis 还突出显示了由于闭包、装箱、枚举器等引起的分配。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。