用途与问题
将一段脚本块保存后稍晚执行,外部变量可能已经变了。如果希望回调记住创建时的值,需要明确捕获规则,不能只因代码文字里出现变量名,就假定它自动保存了当时的数据。
原理与实现选择
GetNewClosure 创建绑定到新动态模块的脚本块,并将调用者上下文中的局部变量复制进去。样本对整数变量分别保存普通脚本块和闭包,然后改变原变量,比较结果;这不表示所有引用对象都被递归复制。
适用环境与验证范围
适用环境为 PowerShell 7。本页由 AI 辅助撰写与整理;完整受控样本已在本机 PowerShell 7.6 执行并通过检查。除文件元数据样本仅操作自行创建并清理的唯一临时文件外,其余样本只操作内存或局部会话;没有连接生产服务器或修改用户配置。已核对所引 PowerShell 与 .NET 官方资料,未在 Windows PowerShell 5.1 或目标生产环境执行,版本差异需另行验证。
可执行样本
在新的 PowerShell 7 测试会话中运行以下完整代码,保留所有检查语句。先阅读样本的文件与会话影响范围,不要在生产会话中直接替换真实输入;同名函数演示结束后退出该测试会话。
$sampleNumber = 10
$deferred = { $sampleNumber }
$captured = { $sampleNumber }.GetNewClosure()
$sampleNumber = 20
if ((& $deferred) -ne 20) { throw 'Deferred lookup mismatch' }
if ((& $captured) -ne 10) { throw 'Captured value mismatch' }
'Deferred lookup and captured local value distinguished'预期结果与核对
普通脚本块读到二十,捕获局部值的闭包读到十。示例只观察一个整数,没有后台作业、并发线程或生产回调注册,也没有保存敏感数据。
常见误区
对象变量复制可能保留同一引用,之后修改对象仍可能被闭包观察到。闭包也可能延长对象生命周期;不要无意捕获大数据集或机密对象,再把回调长期保存。
适用边界
适用于延后执行逻辑的作用域诊断。跨进程作业与远程会话有独立的数据传递规则,不能把本地闭包当作自动跨进程序列化机制。