我试图模拟一种数据结构和逻辑来处理延迟的日志写入,但是我遇到了一种奇怪的情况。如果返回的arrayList只是一项,则if ([collections.arrayList]$deferredLog = Get-PxDeferredLogItems) {
错误,
Cannot convert the "logged: 07/20/2019 10:56:29" value of type "System.String" to type "System.Collections.ArrayList".
有两个项目就可以了。现在,我知道必须将单个项目的数组强制为数组,因为PS有时由于其自身的优势而过于聪明,但是我认为[collections.arrayList]
的Add方法即使在第一个Add上也产生了arrayList。是我完全误解了,还是我的逻辑在其他地方错误?
我也尝试过像这样转换函数调用的结果
if ([collections.arrayList]$deferredLog = [collections.arrayList](Get-PxDeferredLogItems)) {
,但更糟的是,每次通话都会出错。我还尝试在Main中使用Set-PxDeferredLogItems (New-Object collections.arrayList)
将变量初始化为空的arrayList,而不是在第一次调用Add-PxDeferredLogItem
时将n初始化为空,但这显示出相同的行为,直到延迟的日志包含两项为止。我通过在错误行之后直接将Write-Host更改为Write-Host "Process deferred items $($deferredLog.count)"
来验证这一点,直到出现2之前我都收到了错误,然后一切正常。
function Get-PxDeferredLogItems {
return $script:deferredLogItems
}
function Set-PxDeferredLogItems {
param (
[collections.arrayList]$deferredLog
)
[collections.arrayList]$script:deferredLogItems = $deferredLog
}
function Add-PxDeferredLogItem {
param (
[string]$item
)
if (-not $script:deferredLogItems) {
[collections.arrayList]$script:deferredLogItems = New-Object collections.arrayList
}
[void]$script:deferredLogItems.Add($item)
}
function Add-PxLogContent {
param (
[string]$string
)
function Assert-PxWrite {
if ((Get-Random -minimum:1 -maximum:4) -gt 1) {
return $true
} else {
return $false
}
}
if ([collections.arrayList]$deferredLog = Get-PxDeferredLogItems) {
Write-Host "Process deferred items"
:deferredItemsWrite do {
if (Assert-PxWrite) {
Write-Host "$($deferredLog[0]) ($(Get-Date))"
$deferredLog.RemoveAt(0)
} else {
break :deferredItemsWrite
}
} while ($deferredLog.count -gt 0)
if ($deferredLog.count -eq 0) {
$deferredLogPending = $false
} else {
$deferredLogPending = $true
}
Set-PxDeferredLogItems $deferredLog
} else {
$deferredLogPending = $false
}
if (-not $deferredLogPending) {
if (Assert-PxWrite) {
Write-Host $string
} else {
Add-PxDeferredLogItem $string
}
} else {
Add-PxDeferredLogItem $string
}
}
### MAIN
$startTime = Get-Date
$endTime = $startTime + (New-TimeSpan -minutes:2)
Clear-Host
do {
Add-PxLogContent "logged: $(Get-Date)"
Start-SLeep -s:5
} while ((Get-Date) -lt $endTime)
if ($deferredLog = Get-PxDeferredLogItems) {
foreach ($item in $deferredLog) {
Write-Host "!$item"
}
}
编辑:这似乎与传递arrayList有关,因为在不涉及任何函数的情况下,此操作可以按预期工作。
Clear-Host
$deferredLogItems = New-Object collections.arrayList
Write-Host "$($deferredLogItems.getType()) $($deferredLogItems.count) $deferredLogItems"
[void]$deferredLogItems.Add('One')
Write-Host "$($deferredLogItems.getType()) $($deferredLogItems.count) $deferredLogItems"
[void]$deferredLogItems.Add('Two')
Write-Host "$($deferredLogItems.getType()) $($deferredLogItems.count) $deferredLogItems"
[void]$deferredLogItems.Add('Three')
Write-Host "$($deferredLogItems.getType()) $($deferredLogItems.count) $deferredLogItems"
function Get-DeferredLogItems {
if (-not $script:deferredLogItems) {
[collections.arrayList]$script:deferredLogItems = New-Object collections.arrayList
}
[void]$script:deferredLogItems.Add("$($script:deferredLogItems.count + 1)")
return $script:deferredLogItems
}
$script:deferredLogItems = $localDeferredLogItems = $null
foreach ($i in 1..5) {
[collections.arrayList]$localDeferredLogItems = Get-DeferredLogItems
Write-Host "$($localDeferredLogItems.getType()) $($localDeferredLogItems.count) $localDeferredLogItems"
}
EDIT2:由于混乱,用实际的令人反感的代码行替换了#行引用。
EDIT3:值得一试的是,将Get-DeferredLogItems
的结果强制为数组确实可以工作。但是我仍然想知道为什么甚至需要这样做。为什么Add方法在第一次添加时会产生正确的arrayList,但是当作为返回值传递时,PowerShell会@%#$加起来。