2017-09-07 2 views
2

Quelqu'un peut-il expliquer cet étrange comportement PowerShell.System.Collections.ArrayList devient System.Collecitons.HashTable

Si je déclare ce qui suit:

$MyCollection = New-Object System.Collections.ArrayList 

$MyCollection.Add(@{'Val1'=1; 'Val2'=2; 'Val3'=3}) 
$MyCollection.Add(@{'Val1'=1; 'Val2'=2; 'Val3'=3}) 
$MyCollection.Add(@{'Val1'=1; 'Val2'=2; 'Val3'=3}) 

Alors ... Je devrais avoir un objet qui ressemble à ceci:

System.Collections.Array.List 
Index Item 
0  {System.Collections.HashTable} 
1  {System.Collections.HashTable} 
2  {System.Collections.HashTable} 

Cependant, si je reçois membre, vous verrez tout mon colleciton est devenu une grande table de hachage

$MyCollection | Get-Member 

TypeName: System.Collections.Hashtable 

Name    MemberType   Definition                                           
----    ----------   ----------                                           
Add    Method    void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, System.Object value)                  
Clear    Method    void Clear(), void IDictionary.Clear()                                    
Clone    Method    System.Object Clone(), System.Object ICloneable.Clone()                                
Contains   Method    bool Contains(System.Object key), bool IDictionary.Contains(System.Object key)                          
ContainsKey  Method    bool ContainsKey(System.Object key)                                     
ContainsValue  Method    bool ContainsValue(System.Object value)                                    
CopyTo   Method    void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array array, int index)                       
Equals   Method    bool Equals(System.Object obj)                                      
GetEnumerator  Method    System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections.IDictionaryEnumerator IDictionary.GetEnumerator(), System.Collections.IEnumerator IEnumerable.GetEn... 
GetHashCode  Method    int GetHashCode()                                         
GetObjectData  Method    void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context), void ISerializable.GetObjectData(System.Runtime.... 
GetType   Method    type GetType()                                          
OnDeserialization Method    void OnDeserialization(System.Object sender), void IDeserializationCallback.OnDeserialization(System.Object sender)                 
Remove   Method    void Remove(System.Object key), void IDictionary.Remove(System.Object key)                           
ToString   Method    string ToString()                                         
Item    ParameterizedProperty System.Object Item(System.Object key) {get;set;}                                 
Count    Property    int Count {get;}                                         
IsFixedSize  Property    bool IsFixedSize {get;}                                        
IsReadOnly  Property    bool IsReadOnly {get;}                                        
IsSynchronized Property    bool IsSynchronized {get;}                                       
Keys    Property    System.Collections.ICollection Keys {get;}                                   
SyncRoot   Property    System.Object SyncRoot {get;}                                      
Values   Property    System.Collections.ICollection Values {get;} 

Et le comportement est comme ceci. Par exemple, je ne peux pas accéder à mon objet la façon dont je veux:

$MyCollection | %{$_.Val1} 

sorties

1 
1 
1 

de sortie prévue

1 

Comme vous pouvez le voir, nous avons une grande table de hachage maintenant avec un comportement très étrange. Quelqu'un peut-il expliquer ce que Powershell est en train de faire? Parce qu'il n'accède de manière provocante à un HashTable dans une collection ArrayList.

son comme appeler les cmdlets aplanit ma structure de données en une seule table de hachage

+0

Quelle sortie attendez-vous du '$ MyCollection | % {$ _. Val1} 'exemple? La sortie courante serait comme je l'attendrais pour la syntaxe. – Persistent13

Répondre

4

Lorsque vous passez un tableau via le gazoduc, il est déroula donc dans votre exemple Get-Member est de voir les entrailles du tableau, les tables de hachage.

Pour obtenir le type d'un objet qui est un tableau, vous pouvez utiliser la méthode GetType() et rechercher la propriété name.

$MyCollection.GetType() 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  True  ArrayList        System.Object 

Ansgar Wiechers a montré ci-dessous que vous pouvez également utiliser le paramètre -InputObject pour obtenir le type d'un tableau.

Get-Member -InputObject $MyCollection 

Si vous voulez un seul élément du tableau de sortie de hashage vous devrez spécifier quel index dans le tableau que vous voulez la valeur suivie de la touche Hashtable.

$MyCollection[0]['Val1'] 
1 

L'exemple ci-dessus retourne la valeur stockée dans la clé Val1 du premier objet dans le tableau. Pour obtenir les autres, vous devrez incrémenter le numéro d'index ou changer la clé.

+4

Vous pouvez utiliser 'Get-Member -InputObject $ MyCollection' pour éviter le déroulement. –

+0

Pouvez-vous élaborer sur déroulé? On dirait qu'il a été combiné dans une seule table de hachage. Aussi, si je fais cela 'ForEach-Object -InputObject $ MyCollection -Process {$ _}' Si je passe '$ _' à' Get-Member' ou si je passe '$ MyCollection' à' Get-Member' le résultat est exactement le même. –

+3

@JamieMarshall Ils signifient que lorsqu'un tableau est passé dans le pipeline, il parcourt automatiquement chaque élément du tableau et évalue chaque élément individuellement. La raison pour laquelle vous ne voyez qu'une seule sortie est que 'Get-Member' ne produit que des résultats uniques pour les éléments qui lui sont passés par le pipeline. – TheMadTechnician