ArrayList 是否已经过时并且永远不应该使用?如果是,我应该使用什么来代替 .Remove() 方法?

问题描述 投票:0回答:1

我听说 ArrayList 是一种非常古老的数据结构,从早期开始就应该“永远”不被使用。我不确定这是否属实,但我想知道是否有更好的数组类型或可以让我在 do while 循环中使用 .Remove() 的东西?

我的代码的简要描述:对于每个SSD,我测试路径是否可访问,如果不是,它将转到下一个SSD,如果可用,它将复制文件并从阵列列表中删除该SSD,所以我只能尝试在第一次运行失败的 SSD 上再次运行循环,直到达到 $maxAttempts,否则它将在 $maxAttempts 之前完成每个 SSD 的文件复制。另外,如果您认为我的代码和逻辑可以改进,请告诉我,我仍在学习:)

感谢adv,很高兴学习新东西

[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
powershell
1个回答
0
投票

ArrayList 不推荐,逻辑是“列表在所有方面都比 ArrayList 更好,没有真正的理由再使用它们”

按照文档的建议,替代方案是 List。其工作原理几乎相同,除了:

  1. 您需要指定它正在收集的对象的类型(如有疑问,只需使用
    [object]
  2. .Add()
    方法不返回任何内容。不再将其归零!是啊!

...这基本上意味着您可以将所有

[System.Collections.ArrayList]
大量替换为
[System.Collections.Generic.List[object]]
并忘记它。
但请不要并逐一检查一切是否正常。
还因为您可以通过使用正确类型的列表来最大限度地提高效率。例如,在您的代码中,它将是
[System.Collections.Generic.List[string]]

在您的用例中没有太大区别。

至于逻辑上的改进:有一些。

# arrays and collections don't need end-line commas
# each line is automatically identified as its own entry
[System.Collections.Generic.List[string]]$DestSSD = @(
    # 'B:\'
    # 'A:\'
    'T:\'
)

$Source = 'c:\source'

######__MAIN__######

# Because we are repeating the steps for a KNOWN number of times, the FOR loop is the best choice
# in this form it will start with $RemainingAttempts equal to 3
# il will keep going as long as $MaxAttempt is true, which in this case means "greater than 0"
# will reduce $RemainingAttempts by 1 AFTER checking if it still $true==greater than 0
for ($RemainingAttempts = 3; $RemainingAttempts ; $RemainingAttempts--) {

    Write-Host "Remaining Attempts: $RemainingAttempts"
    # by using ToArray we are, basically, working on a temporary virtual copy of $DestSSD updated each loop, which let us modifying the original
    # There might be more efficient ways to manage this, but this seems the easiest to read and given the size of the collection the difference is probably imperceptible
    $DestSSD.ToArray().foreach({
            # not necessary but makes easier to read.
            $Disk = $_
            Write-Host "Accessing SSD: $Disk"
            if (Test-Path $Disk) {
                robocopy $Source $Disk /COPY:DAT /R:0 /np /tee /LOG+:"C:\Documents\logs\SSD_LOG.log"
                Write-Host 'Copy successful!'

                # .Remove() returns a boolean in 5.1 but not in 7.x
                # Nullying it to maximise compatibility
                $null = $DestSSD.Remove($Disk)

                # check if the now updated $DestSSD has still elements, and loads the value in $TotalSSD
                if ($RemainingSSD = $DestSSD.Count) {
                    Write-Host "Remaining SSDs to check: $RemainingSSD"
                }
                else {
                    Write-Host 'Last SSD copy finished!'
                    # Break does, in fact, break the loop only
                    # Exit, otherwise, would close the whole script
                    break
                }
            }
            else {
                Write-Host 'Copy failed... Trying again later!'
            }
        })
    # instead of waiting at the end of a single failure, it's better to wait at the end of a single loop(unless we have completed the job and broken out)
    Write-Host 'waiting 1 sec'
    # Start-Sleep -Seconds 1
}
# if $DestSSD.Count is $true as in: greater than 0, some failed
if ($DestSSD.Count) {
    Write-Host 'Max attempts reached!' 
    Write-Host ('Failed to copy on drives {0}' -f ($DestSSD -join ', ') )
}
© www.soinside.com 2019 - 2024. All rights reserved.