传递Delegate时修改变量的实现方案求助
问题
我采用了传递委托至函数的方案,希望在catch块每次捕获错误时修改$inputarg文本,例如在字符串末尾追加attempts的值,预期输出如下:
Oh no! It happened again! 1 Oh no! It happened again! 2 Oh no! It happened again! 3
我尝试了以下代码,但未能成功实现。请问如何实现Invoke的重载?或者是否有其他更合适的方法?
function Retry([Action]$action, $varToChange) { $attempts=3 $sleepInSeconds=1 do { try { $action.Invoke($varToChange); break; } catch [Exception] { Write-Host $_.Exception.Message $varTochange = $varTochange + $attempts } $attempts-- if ($attempts -gt 0) { Start-Sleep $sleepInSeconds } } while ($attempts -gt 0) } function MyFunction($inputArg) { Throw $inputArg } #Example of a call: Retry({MyFunction "It ran this many times : "}) 'It ran this many times : '
解决方案
原代码的核心问题
- 脚本块未使用传入参数:调用
Retry时,第一个参数的脚本块硬编码了字符串,没有用到传入的$varToChange,导致委托调用时根本没使用你想修改的变量。 - 值类型传递限制:字符串是值类型,在
Retry函数内修改$varToChange只是修改了局部副本,不会影响外部变量。 - 变量拼写错误:
catch块里的$varTochange(小写c)和参数名$varToChange(大写C)不一致,导致赋值无效。
修正方案一:使用引用类型包装参数
用PSCustomObject包装字符串,借助引用类型的特性,让函数内的修改同步到外部:
function Retry([Action[object]]$action, $varContainer) { $attempts = 1 $maxAttempts = 3 $sleepInSeconds = 1 do { try { $action.Invoke($varContainer); break; } catch [Exception] { Write-Host $_.Exception.Message # 修改包装对象的属性,外部会同步更新 $varContainer.Value = "$($varContainer.Value) $attempts" } $attempts++ if ($attempts -le $maxAttempts) { Start-Sleep $sleepInSeconds } } while ($attempts -le $maxAttempts) } function MyFunction($inputArg) { Throw $inputArg.Value } # 用PSObject包装初始字符串 $inputVar = [PSCustomObject]@{ Value = "Oh no! It happened again!" } # 调用Retry,脚本块使用传入的参数 Retry({ MyFunction $_ }, $inputVar)
修正方案二:使用[ref]传递变量引用
通过[ref]标记变量,让函数直接修改外部变量的实际值:
function Retry([Action]$action, [ref]$varToChange) { $attempts = 1 $maxAttempts = 3 $sleepInSeconds = 1 do { try { $action.Invoke(); break; } catch [Exception] { Write-Host $_.Exception.Message # 通过ref修改变量的实际值 $varToChange.Value = "$($varToChange.Value) $attempts" } $attempts++ if ($attempts -le $maxAttempts) { Start-Sleep $sleepInSeconds } } while ($attempts -le $maxAttempts) } function MyFunction($inputArg) { Throw $inputArg } $inputVar = "Oh no! It happened again!" # 用[ref]传递变量引用,脚本块直接使用外部变量 Retry({ MyFunction $inputVar }, [ref]$inputVar)
两种方案运行后都会输出符合预期的结果:
Oh no! It happened again! 1 Oh no! It happened again! 1 2 Oh no! It happened again! 1 2 3
内容的提问来源于stack exchange,提问作者TheEnglishmanUK
相关产品推荐
相关产品推荐

