Why does a System.Array object have an Add() method?

  • A+

I fully understand that a System.Array is immutable.

Given that, why does it have an Add() method?

It does not appear in the output of Get-Member.

$a = @('now', 'then') $a.Add('whatever') 

Yes, I know this fails and I know why it fails. I am not asking for suggestions to use [System.Collections.ArrayList] or [System.Collections.Generic.List[object]].


[System.Array] implements [System.Collections.IList], and the latter has an .Add() method.

That Array implements IList, which is an interface that also covers resizable collections, may be surprising - it sounds like there are historical reasons for it.

In C#, this surprise is hard to stumble upon, because you need to explicitly cast to IList or use an IList-typed variable in order to even access the .Add() method.

By contrast, since version 3, PowerShell surfaces even a type's explicit interface implementations as direct members of a given type's instance. (Explicit interface implementations are those referencing the interface explicitly in their implementation, such as IList.Add() rather than just .Add()).

As a byproduct of this design, in PowerShell the .Add() method can be called directly on System.Array instances, which makes it easier to stumble upon the problem, because you may not realize that you're invoking an interface method. In the case of an array, the IList.Add() implementation (rightfully) throws an exception stating that Collection was of a fixed size; the latter is an exception of type NotSupportedException, which is how types implementing an interface are expected to report non-support for parts of an interface.

What helps is that the Get-Member cmdlet and even just referencing a method without invoking it - simply by omitting () - allow you to inspect a method to determine whether it is native to the type or an interface implementation:

PS> (1, 2).Add  # Inspect the definition of a sample array's .Add() method  OverloadDefinitions ------------------- int IList.Add(System.Object value) 

As you can see, the output reveals that the .Add() method belongs to the Ilist interface.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: