You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

传递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 : '
解决方案

原代码的核心问题

  1. 脚本块未使用传入参数:调用Retry时,第一个参数的脚本块硬编码了字符串,没有用到传入的$varToChange,导致委托调用时根本没使用你想修改的变量。
  2. 值类型传递限制:字符串是值类型,在Retry函数内修改$varToChange只是修改了局部副本,不会影响外部变量。
  3. 变量拼写错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:33:30