【问题标题】:System.Collections.ArrayList becomes System.Collecitons.HashTableSystem.Collections.ArrayList 变为 System.Collections.HashTable
【发布时间】:2018-02-16 17:43:54
【问题描述】:

谁能解释这种奇怪的 powershell 行为。

如果我声明以下内容:

$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})

所以...我应该有一个看起来像这样的对象:

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

但是,如果我获得会员,您会看到我的整个收藏都变成了一个大哈希表

$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;}

而且行为是这样的。例如,我无法以我想要的方式访问我的对象:

$MyCollection | %{$_.Val1} 

输出

1
1
1

预期输出

1

如您所见,我们现在有一个具有非常奇怪行为的大型哈希表。谁能解释一下Powershell实际上在做什么?因为它绝对不会访问 ArrayList 集合中的 HashTable。

它就像调用任何 cmdlet 一样将我的数据结构扁平化为单个哈希表

【问题讨论】:

  • 您希望$MyCollection | %{$_.Val1} 示例的输出是什么?当前输出将与我对语法的期望一样。

标签: powershell arraylist collections hashtable


【解决方案1】:

当您通过管道传递数组时,它会展开,因此在您的示例中 Get-Member 看到的是数组的内部结构,即哈希表。

要获取数组对象的类型,您可以使用 GetType() 方法并查看 name 属性。

$MyCollection.GetType()

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

Ansgar Wiechers 在下面展示了您还可以使用-InputObject 参数来获取数组的类型。

Get-Member -InputObject $MyCollection

如果您只需要哈希表输出数组中的单个项目,则需要指定数组中的哪个索引您希望该值后跟哈希表键。

$MyCollection[0]['Val1']
1

上面的示例返回存储在数组中第一个对象的键Val1 中的值。要获得其他人,您必须增加索引号或更改键。

【讨论】:

  • 您可以使用Get-Member -InputObject $MyCollection 来避免展开。
  • 你能详细说明展开吗?看起来它被组合成一个哈希表。另外,如果我这样做ForEach-Object -InputObject $MyCollection -Process {$_ } 如果我将$_ 传递给Get-Member 或者我将$MyCollection 传递给Get-Member,结果是完全相同的。
  • @JamieMarshall 他们的意思是当一个数组通过管道时,它会自动遍历数组中的每个项目并单独评估每个项目。您只看到一个输出的原因是 Get-Member 仅输出通过管道传递给它的项目的唯一结果。
猜你喜欢
  • 2021-12-03
  • 2013-03-22
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-01
相关资源
最近更新 更多