ArrayList是否已过时?求支持.Remove()的替代类型及代码优化建议
关于PowerShell中ArrayList替代方案及代码优化的问题
问题描述
听说ArrayList是老旧的数据结构,不该再用,对此我有疑问。想知道有没有更优的数组类型可以在do while循环里使用
.Remove()方法?我的代码逻辑:遍历
DestSSD中的每个SSD,用Test-Path检测是否可访问,不可访问就跳过;可访问则执行文件复制,然后把该SSD从列表中移除。只对首次尝试失败的SSD重复执行循环,直到达到$maxAttempts(最多3次)或所有SSD复制完成。另外,希望能得到代码和逻辑的优化建议,我还在学习中。
原代码
[System.Collections.ArrayList]$DestSSD = @( "B:\", "A:\", "T:\" ) $Source="c:\source" $maxAttempts = 3 $attempts = 0 ######__MAIN__###### do { $attempts++ foreach ($ssd in $($DestSSD)) { Write-Host "Accessing SSD: "$ssd if (Test-Path $ssd ) { #Copy File below robocopy $Source $ssd /COPY:DAT /R:0 /np /tee /LOG+:"C:\Documents\logs\SSD_LOG.log" Write-Host "Copy successful!" $DestSSD.Remove($ssd) Write-Host "Remained SSDs to check: "$DestSSD.Count if($DestSSD.Count -eq 0){ "Last SSD copy finished!" Exit } }else { Write-Host "Copy failed... Trying again!" Start-Sleep -s 5 } } } while ($attempts -lt $maxAttempts) #3 attemps with -lt (Less Than) Write-Host "Max attempts reached!" Exit
一、ArrayList的替代方案
推荐使用 System.Collections.Generic.List[string],这是现代且类型安全的泛型列表,性能优于ArrayList,同样支持.Remove()方法,用法和ArrayList高度兼容:
# 声明方式 $DestSSD = [System.Collections.Generic.List[string]]@("B:\", "A:\", "T:\")
二、代码与逻辑优化建议
核心优化点
- 避免遍历中直接修改原列表:原代码通过
$($DestSSD)创建副本,但直接调用.Remove()仍可能引发意外逻辑问题,建议维护独立的待重试列表。 - 精准处理重试逻辑:仅对每次尝试失败的SSD进行重试,避免重复处理已成功的目标。
- 完善错误判断:robocopy的退出码0/1均表示成功,需针对性判断复制结果,而非仅依赖路径检测。
- 避免强制终止脚本:用
break替代Exit,更优雅地控制流程。
优化后代码
# 使用泛型List替代ArrayList $DestSSD = [System.Collections.Generic.List[string]]@("B:\", "A:\", "T:\") $Source = "c:\source" $maxAttempts = 3 $logPath = "C:\Documents\logs\SSD_LOG.log" # 确保日志目录存在 $logDir = Split-Path -Path $logPath -Parent if (-not (Test-Path -Path $logDir)) { New-Item -Path $logDir -ItemType Directory | Out-Null } # 初始化待重试列表 $retrySSDs = $DestSSD.Clone() for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) { Write-Host "=== 第 $attempt 次尝试 ===" # 临时存储本次尝试失败的SSD $failedSSDs = [System.Collections.Generic.List[string]]@() foreach ($ssd in $retrySSDs) { Write-Host "正在访问SSD: $ssd" # 明确检测目标是否为可访问的目录 if (Test-Path -Path $ssd -PathType Container) { # 执行文件复制 robocopy $Source $ssd /COPY:DAT /R:0 /np /tee /LOG+:$logPath # 检查robocopy退出码:0=无文件需复制,1=复制成功,均视为成功 if ($LASTEXITCODE -le 1) { Write-Host "复制成功!已移除SSD: $ssd" $DestSSD.Remove($ssd) } else { Write-Host "复制失败(退出码: $LASTEXITCODE),将重试SSD: $ssd" $failedSSDs.Add($ssd) Start-Sleep -Seconds 5 } } else { Write-Host "SSD不可访问,将重试SSD: $ssd" $failedSSDs.Add($ssd) Start-Sleep -Seconds 5 } } # 更新待重试列表为本次失败的SSD $retrySSDs = $failedSSDs # 无待重试目标则提前结束循环 if ($retrySSDs.Count -eq 0) { Write-Host "所有SSD复制完成!" break } Write-Host "第 $attempt 次尝试结束,剩余待重试SSD数量: $($retrySSDs.Count)`n" } # 输出最终结果 if ($retrySSDs.Count -gt 0) { Write-Host "已达到最大尝试次数 ($maxAttempts),以下SSD复制失败: $($retrySSDs -join ', ')" }
内容的提问来源于stack exchange,提问作者Filip
相关产品推荐
相关产品推荐

