ChatGPT解决这个技术问题 Extra ChatGPT

Array.Add vs +=

I've found some interesting behaviour in PowerShell Arrays, namely, if I declare an array as:

$array = @()

And then try to add items to it using the $array.Add("item") method, I receive the following error:

Exception calling "Add" with "1" argument(s): "Collection was of a fixed size."

However, if I append items using $array += "item", the item is accepted without a problem and the "fixed size" restriction doesn't seem to apply.

Why is this?


F
Frode F.

When using the $array.Add()-method, you're trying to add the element into the existing array. An array is a collection of fixed size, so you will receive an error because it can't be extended.

$array += $element creates a new array with the same elements as old one + the new item, and this new larger array replaces the old one in the $array-variable

You can use the += operator to add an element to an array. When you use it, Windows PowerShell actually creates a new array with the values of the original array and the added value. For example, to add an element with a value of 200 to the array in the $a variable, type: $a += 200

Source: about_Arrays

+= is an expensive operation, so when you need to add many items you should try to add them in as few operations as possible, ex:

$arr = 1..3    #Array
$arr += (4..5) #Combine with another array in a single write-operation

$arr.Count
5

If that's not possible, consider using a more efficient collection like List or ArrayList (see the other answer).


Thanks :) Thought it may be something like this but thought it would inefficient with large arrays, so the powershell team were doing something different.
It depends. If you are going to add and remove a lot of members then yes, try List or ArrayList. They will be much faster. I personally use += and array 99% of the time because I usually create short throw-away scripts where the extra seconds doesn't matter. For big scripts with lots of add/remove where I want to optimize and save time I use List or ArrayList.
As arrays are always of a fixed size, does anyone know why the Add() method exists?
Because it's inherited from IList. Try Get-Member -InputObject @() will show this Add Method int IList.Add(System.Object value)
So they have .Add() because they implement IList, but it doesn't work because they are .IsFixedSize. So why are they fixed size?? Why does IList have an property to check for a fixed size list thing?
S
Sebastian Kaczmarek

If you want a dynamically sized array, then you should make a list. Not only will you get the .Add() functionality, but as @frode-f explains, dynamic arrays are more memory efficient and a better practice anyway.

And it's so easy to use.

Instead of your array declaration, try this:

$outItems = New-Object System.Collections.Generic.List[System.Object]

Adding items is simple.

$outItems.Add(1)
$outItems.Add("hi")

And if you really want an array when you're done, there's a function for that too.

$outItems.ToArray()

I have tried this. I create it using New-Object System.Collections.Generic.List[string] but then if I do .GetType, it tells me it is an array.
Have you tried using the Add() function? I can confirm, if you create a generic List object as stated above, you have a mutable list for which you can add and remove items using the Add() and Remove() methods respectively.
@Preza8: (New-Object System.Collections.Generic.List[string]).GetType().Name yields List`1 for me, as expected; perhaps you applied += to the variable containing the list (rather than calling the .Add() method), in which case the variable value would indeed be converted to an array (System.Object[]).
Shortcut: $a = new-object collections.generic.list[object]
is this the same as: $arr = New-Object System.Collections.ArrayList?
j
js2010

The most common idiom for creating an array without using the inefficient += is something like this, from the output of a loop:

$array = foreach($i in 1..10) { 
  $i
}
$array

Adding to a preexisting array:

[collections.arraylist]$array = 1..10
$array.add(11) > $null

I really like this approach. It's much more succinct without loss of intent/clarity
@js2010 Don't quite understand this. How would you APPEND a new value to an existing array using this approach?
@Jay I think that comes up less often, but an arraylist would be more efficient than copying the whole array over again with +=.