给定正确定义的变量
$test = New-Object System.Collections.ArrayList
.Add
使用数组中的项目计数污染管道,而.AddRange
则不污染管道。$test.Add('Single')
会将计数转储到控制台。 $test.AddRange(@('Single2'))
将很干净,无需额外的努力。为什么会有不同的行为?只是一个疏忽,还是我不了解某些故意行为?鉴于
.AddRange
在不使用变量(已经是数组)时需要强制转换为数组,当我知道只需要添加一项时,我倾向于使用[void]$variable.Add('String')
,而在向数组添加数组时,甚至倾向于使用[void]$test.AddRange($variable)
,即使当$variable
仅包含或只能包含单个项目时。这里的[void]
不是必需的,但是我想知道是否拥有它只是最佳实践,这当然取决于上面的答案。还是我在那里也想念东西? 最佳答案
因为很多年前,有人认为ArrayList
应该如何表现!Add()
返回将参数插入列表的索引,这确实有用,并且很有意义。
另一方面,对于AddRange()
,尚不清楚为什么应返回任何内容,如果是,则返回什么?输入参数中第一项的索引?最后?还是应该返回带有所有插入索引的可变大小数组?那太尴尬了!因此,无论谁实现ArrayList
,都决定根本不返回任何内容。
在最初设计C#
的VB.NET
或ArrayList
中,“污染管道”这个概念实际上并不存在,如果有人在不分配变量的情况下调用.Add()
,则运行时会简单地将返回值复制回调用方。
不,这完全没有必要。 AddRange()
并非神奇地有一天会改变为输出任何东西。
如果您不需要知道插入索引,请改用 [System.Collections.Generic.List[psobject]]
:
$list = [System.Collections.Generic.List[psobject]]::new()
# this won't return anything, no need for `[void]`
$list.Add(123)
如果您出于某种原因必须使用
ArrayList
,则可以通过覆盖Add()
方法来使其“沉默”:function New-SilentArrayList {
# Create a new ArrayList
$newList = [System.Collections.ArrayList]::new()
# Create a new `Add()` method, then return the list
$newAdd = @{
InputObject = $newList
MemberType = 'ScriptMethod'
Name = 'Add'
Value = {param($obj) $this.AddRange(@($obj))}
}
Write-Output $(
Add-Member @newAdd -Force -PassThru
) -NoEnumerate
}
现在,您的
ArrayList
的Add()
再也不会窥视了!PS C:\> $list = New-SilentArrayList
PS C:\> $list.Add(123)
PS C:\> $list
123