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

PowerShell中[Generic.List].ForEach()方法如何引用传入项

用.NET泛型List的.ForEach()方法替换字符串前缀的解决方案

场景说明

现有一个String类型的.NET泛型List:

$log = [System.Collections.Generic.List[String]]::new()
$log.Add('?_Label')
$log.Add('=_Item')

通过管道+Foreach-Object可以实现前缀替换:

$log | Foreach-Object {$_ -replace '^\?_', 'E_'}

但尝试使用.NET原生List<T>.ForEach()方法时,几种写法均无效:

$log.ForEach({$_ -replace '^\?_', 'E_' })
$log.ForEach({$arg -replace '^\?_', 'E_' })
$log.ForEach({param([String] $item) $item -replace '^\?_', 'E_' })

关键区别:两个ForEach方法

要解决问题,首先要区分两种不同的ForEach:

  • PowerShell原生.ForEach():PowerShell为所有集合添加的扩展方法,会返回处理后的元素集合,支持用$_指代当前元素,和Foreach-Object管道效果一致。
  • .NET List<T>.ForEach():List<T>类的内置方法,仅接受Action<T>委托,无返回值,仅用于遍历执行操作,不会自动返回处理结果。

正确实现方式

方式1:用PowerShell原生.ForEach()(推荐,和管道效果一致)

直接使用PowerShell为集合添加的.ForEach()方法,写法简单且能返回处理后的集合:

# 得到处理后的新集合,原$log不受影响
$processedLog = $log.ForEach({ $_ -replace '^\?_', 'E_' })

方式2:用.NET List<T>.ForEach()修改原集合

如果一定要使用.NET原生方法,需要将脚本块转换为Action<String>委托,并且因为字符串是不可变类型,要通过索引修改原List的元素:

$index = 0
$log.ForEach([Action[String]]{
    param([string]$item)
    # 修改原List对应索引的元素
    $log[$index] = $item -replace '^\?_', 'E_'
    # 索引自增,必须用script:作用域修改外部变量
    $script:index++
})
# 执行后原$log已被修改,其中'?_Label'变为'E_Label'

为什么之前的写法无效

  1. .NET的List<T>.ForEach()必须接收Action<T>类型的委托,直接传入未转换的脚本块会导致PowerShell无法识别;
  2. $arg不是PowerShell脚本块中当前元素的指代符,正确的参数需要通过param定义并配合委托类型;
  3. 即使定义了param,如果不转换为Action<String>委托,.NET方法无法匹配参数类型,因此执行失败。

内容的提问来源于stack exchange,提问作者Gordon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:05:15