【发布时间】:2023-04-02 11:25:03
【问题描述】:
好的,我将把问题改写为更通用和更完整。但我将原始帖子留在底部。
给定:一个变量$queue,我想向其中添加不同种类和大小的集合,这些集合可以是本地创建的变量,也可以是从函数传递的结果。
在处理$queue 时,我想避免+=,因此不能选择简单的数组。
我需要能够添加可变大小的集合,因此需要支持.AddRange(),因为它可以处理单个项目集合和更大的集合。
我需要支持 Windows 7/PS2 以及 Windows 10/PS5
[System.Collections.ArrayList] 已被弃用,所以这并不理想。
这使得System.Collections.Generic.List[string] 成为$queue 的类型
此外,我需要添加到$queue 的大多数地方可能最多有几百个,但可能有超过 1000 个地方定义了各种其他集合。因此,让所有其他集合也使用System.Collections.Generic.List[string] 将是非常有问题的。即使只是在返回之前进行铸造也是一项繁重的工作。所以我真的想在$queue.AddRange() 内进行干预。
这也是一个短期重构和错误修复版本(一些错误与这些东西有关),在彻底重写为类之前,其中 100% 的这些集合将是System.Collections.Generic.List[string],并且会少很多冗余代码。
此外,现在希望获得最简单、最易读的代码,以使重写尽可能容易。
所以,理想情况下这是可行的
$queue = New-Object System.Collections.Generic.List[string]
$array1 = @('array1.1')
$array3 = @('array3.1', 'array3.2', 'array3.3')
$arrayList1 = [System.Collections.ArrayList]@('arrayList1.1')
$arrayList3 = [System.Collections.ArrayList]@('arrayList3.1', 'arrayList3.2', 'arrayList3.3')
$genericList1 = [System.Collections.Generic.List[string]]@('genericList1.1')
$genericList3 = [System.Collections.Generic.List[string]]@('genericList3.1', 'genericList3.2', 'genericList3.3')
function ReturnArray ([int]$count) {
$return = @()
foreach ($i in 1..$count) {
$return += "ArrayFunction$($count).$($i)"
}
return $return
}
function ReturnArrayList ([int]$count) {
$return = New-Object System.Collections.ArrayList
foreach ($i in 1..$count) {
$return.Add("ArrayListFunction$($count).$($i)") > $null
}
return $return
}
function ReturnGenericList ([int]$count) {
$return = New-Object System.Collections.Generic.List[string]
foreach ($i in 1..$count) {
$return.Add("GenericList[string]Function$($count).$($i)")
}
return $return
}
CLS
$queue.AddRange($array1)
$queue.AddRange($array3)
$queue.AddRange($arrayList1)
$queue.AddRange($arrayList3)
$queue.AddRange($genericList1)
$queue.AddRange($genericList3)
$returnValue = ReturnArray 1
$queue.AddRange($returnValue)
$returnValue = ReturnArray 3
$queue.AddRange($returnValue)
$returnValue = ReturnArrayList 1
$queue.AddRange($returnValue)
$returnValue = ReturnArrayList 3
$queue.AddRange($returnValue)
$returnValue = ReturnGenericList 1
$queue.AddRange($returnValue)
$returnValue = ReturnGenericList 3
$queue.AddRange($returnValue)
$queue
这在许多方面都存在问题。当从函数返回单个元素数组时,它会展开,因此.AddRange() 不起作用。但我想避免像这样重新排列所有内容
$queue.AddRange(@($variable))
在 Windows 10 中,像这样将所有内容都转换为 [System.Collections.Generic.List[string]],并且使用类型加速器甚至可以读取。但这在 Windows 7/PS2 中失败。
$queue.AddRange([System.Collections.Generic.List[string]]$array1)
$queue.AddRange([System.Collections.Generic.List[string]]$array3)
$queue.AddRange([System.Collections.Generic.List[string]]$arrayList1)
$queue.AddRange([System.Collections.Generic.List[string]]$arrayList3)
$queue.AddRange([System.Collections.Generic.List[string]]$genericList1)
$queue.AddRange([System.Collections.Generic.List[string]]$genericList3)
$returnValue = ReturnArray 1
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnArray 3
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnArrayList 1
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnArrayList 3
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnGenericList 1
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnGenericList 3
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
所以,简而言之,问题是;是否有一种单一的、可读的、高性能的方法可以在 Win7/PS2 和 Win10/PS5 中进行这项工作?令人沮丧的是,似乎使用[System.Collections.ArrayList] 实际上更容易一些。但是,在弃用和.Add() 污染管道之间,这发生在很多函数中,这也不是一种选择。
希望这能澄清问题的范围。
原帖
我正在重构一些代码以使用通用列表与数组,因为一些数组变得越来越大,我更喜欢.Add() 和.AddRange() 而不是+=。
但是,我有很多代码,我可能无法一次重构所有内容。所以我会有一些地方需要将数组添加到数组列表中,有时数组来自函数。我的感觉是,目前最好的方法就是在我添加的位置将数组转换为数组列表,例如......
$list.AddRange([System.Collections.Generic.List[string]]$array)
然后,一旦我替换了简单数组使用的每个实例,我就可以返回清理不必要的强制转换。这是我最好的前进方式,还是我错过了更简单的答案?
此外,在相关说明中,在我看来,使用
定义我自己的类型加速器$Accelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
$Accelerators::Add("PxStringList","System.Collections.Generic.List[string]")
可能是个好主意。自从
$list.AddRange([PxStringList]$array)
比阅读更容易
$list.AddRange([System.Collections.Generic.List[string]]$array)
再次,我是在正确的轨道上,还是遗漏了一些明显的东西?
编辑:如果有人想知道故障模式,这是对我提出问题的代码的 sn-p。这在 Windows 7 和 Windows 10 中失败。
$validFontExtentions = @('.ttf', '.txt')
$fontQueue = New-Object System.Collections.Generic.List[string]
$fontQueue.AddRange($validFontExtentions)
【问题讨论】:
-
问题是什么?
-
@mathias-r-jessen,问题是,当我执行 AddRange 时进行强制转换是处理可能添加的数组的最佳方式吗?正如 JosefZ 指出的那样,可以展开您添加的任何内容,但我的感觉是该案例更具可读性,并且是短期需求。但即使是短期解决方案,我也不想做对。
-
$fontQueue.AddRange([System.Collections.Generic.IEnumerable[string]]$validFontCollection) -
@JosefZ,
Generic.List和Generic.IEnumerable有什么区别?我见过的例子都只提到了List。好吧,或者他们提到[arralylist],我听说它已被弃用,所以我也试图避免这种情况。 -
如果
$list是ArrayLIst没关系 - 另一方面,如果$list是通用集合,它通常会接受任何IEnumerable<T>,包括平面数组,所以你可以使用$list.AddRange([string[]]$array),或者如果你不知道类型参数:$list.AddRange($array -as "$($list.GetType().GenericTypeArguments[0])[]")。不过,我仍然不清楚问题是什么,我们要在这里解决的确切问题是什么?
标签: arrays powershell arraylist casting