First: collections are enumerated, when passed by pipeline, so in this case $Array | gm
Get-Member
cmdlet does not see an array, but individual items of it, so it report members of items not members of array.
Second: arrays implement IList
interface, and single dimensions zero-based arrays also implement generic version of that interface. Some interface methods are implemented explicitly, like Add
or Contains
.
Consider this code:
Add-Type -TypeDefinition @'
using System;
public interface IInterface {
void Method();
}
public class Class1:IInterface {
void IInterface.Method() {
throw new NotSupportedException();
}
}
public class Class2:IInterface {
void IInterface.Method() {
//Do something.
}
}
'@
(New-Object Class1).Method()
(New-Object Class2).Method()
([IInterface](New-Object Class1)).Method()
([IInterface](New-Object Class2)).Method()
Try run it in PowerShell v2. All Method
calls failed with error Method invocation failed because [Class] doesn't contain a method named 'Method'.
It is true, nor Class1
nor Class2
have Method
method. So the problem: how to call interface method if class implement it explicitly?
In PowerShell v3 that changed. All interface methods now also reported as members of object, so call (New-Object Class2).Method()
works. Problem is that PowerShell does not have a way to know why interface method was implemented explicitly, because it not supported or because it intended to call thru interface, so it have to report Method
as member for Class1
and Class2
, even if Class1
does not actually support than member.
For example IList.Contains
is valid call for array but this code:
$a=1..10
$a.Contains(5)
fails in PowerShell v2:
function f{
param(
[Collections.IList]$List,
[Object]$Item
)
$List.Contains($Item)
}
$Array=1..10
$List=New-Object Collections.Generic.List[Object] (,$Array)
f $Array 5 #This will fail in PowerShell v2
f $List 5