about_Member-Access_Enumeration
Describe la enumeración automática de colecciones al usar el operador de acceso a miembros.
PowerShell mantiene una lista de tipos que son enumerables. A partir de PowerShell 3.0, la característica de enumeración de acceso a miembros mejora la comodidad de usar el operador de acceso a miembros (.
) en objetos de colección que son enumerables.
La enumeración con acceso de miembro le ayuda a escribir código más simple y corto. En lugar de canalizar un objeto de colección a ForEach-Object
o usar el ForEach()
método intrínseco para acceder a los miembros de cada elemento de la colección, puede utilizar el operador de acceso a miembros en el objeto de colección.
Los ejemplos siguientes producen los mismos resultados. El último ejemplo demuestra el uso del operador de acceso a miembros:
PS> Get-Service -Name event* | ForEach-Object -Process { $_.DisplayName }
Windows Event Log
COM+ Event System
PS> (Get-Service -Name event*).ForEach({ $_.DisplayName })
Windows Event Log
COM+ Event System
PS> (Get-Service -Name event*).DisplayName
Windows Event Log
COM+ Event System
Nota
Puede usar el operador de acceso a miembros para obtener los valores de una propiedad en los elementos de una colección, pero no puede usarlo para establecerlos directamente. Para obtener más información, consulte about_Arrays. La enumeración de acceso a miembros es una característica útil. Puede haber diferencias sutiles de comportamiento y rendimiento entre los distintos métodos de enumeración.
Cuando se usa el operador de acceso a miembros en un objeto y el miembro especificado existe en ese objeto, se invoca al miembro. Cuando se usa el operador de acceso a miembros en un objeto de colección que no tiene el miembro especificado, PowerShell enumera los elementos de esa colección y usa el operador de acceso a miembros en cada elemento enumerado.
Durante la enumeración de acceso a miembros para una propiedad, el operador devuelve el valor de la propiedad para cada elemento que tenga dicha propiedad. Si ningún elemento tiene la propiedad especificada, el operador devuelve $null
.
Durante la enumeración de acceso de miembros para un método, el operador intenta llamar al método en cada elemento de la colección. Si algún elemento de la colección no tiene el método especificado, el operador devuelve la excepción MethodNotFound.
Advertencia
Durante la enumeración de acceso a miembros para un método, se llama al método en cada elemento de la colección. Si el método al que llama realiza cambios, los cambios se efectuarán para cada elemento de la colección. Si se produce un error durante la enumeración, solo se llamará al método en los elementos enumerados antes del error. Para mayor seguridad, considere la posibilidad de enumerar manualmente los elementos y tratar explícitamente cualquier error.
Cuando se usa el operador de acceso a miembros en un objeto que no es una colección enumerable, PowerShell invoca al miembro para devolver el valor de la propiedad o salida del método para ese objeto.
PS> $MyString = 'abc'
PS> $MyString.Length
3
PS> $MyString.ToUpper()
ABC
Cuando se usa el operador de acceso a miembros en un objeto no enumerable que no tiene el miembro, PowerShell devuelve $null
para la propiedad que falta o un error MethodNotFound para el método que falta.
PS> $MyString = 'abc'
PS> $null -eq $MyString.DoesNotExist
True
PS> $MyString.DoesNotExist()
InvalidOperation: Method invocation failed because [System.String] does not contain a method named 'DoesNotExist'.
Cuando se usa el operador de acceso a miembros en un objeto de colección que tiene el miembro, siempre devuelve el valor de propiedad o el resultado del método para el objeto de colección.
En este ejemplo, los miembros especificados existen en la colección, pero no los elementos que la componen.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b')
PS> $Collection.IsReadOnly
False
PS> $Collection.Add('c')
PS> $Collection
a
b
c
En este ejemplo, los miembros especificados existen tanto en la colección como en los elementos de ella. Compare los resultados de los comandos mediante el operador de acceso a miembros de la colección con los resultados del uso del operador de acceso a miembros en los elementos de colección de ForEach-Object
. En la colección, el operador devuelve el valor de propiedad o el resultado del método para el objeto de colección y no los elementos que contiene.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $Collection.Count
3
PS> $Collection | ForEach-Object -Process { $_.Count }
1
1
1
PS> $Collection.ToString()
System.Collections.Generic.List`1[System.String]
PS> $Collection | ForEach-Object -Process { $_.ToString() }
a
b
c
Nota
Las colecciones que implementan la interfaz System.Collections.IDictionary, como HashTable y OrderedDictionary, tienen un comportamiento diferente. Cuando se utiliza el operador member-access en un diccionario que tiene una clave con el mismo nombre que una propiedad, devuelve el valor de la clave en lugar del de la propiedad.
Puede acceder al valor de la propiedad del objeto de diccionario mediante el miembro intrínseco psbase. Por ejemplo, si el nombre de la clave es keys
y desea devolver la colección de las claves HashTable, utilice esta sintaxis:
$hashtable.psbase.Keys
Cuando se usa el operador de acceso a miembros en un objeto de colección que no tiene el miembro, pero sí lo tienen los elementos que contiene, PowerShell enumera los elementos de la colección y devuelve el valor de la propiedad o el resultado del método para cada elemento.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $Collection.Length
1
1
1
PS> $Collection.ToUpper()
A
B
C
Cuando se usa el operador de acceso a miembros en un objeto de colección que no tiene el miembro y tampoco los elementos, el comando devuelve $null
si especifica una propiedad o un error de MethodNotFound
si especifica un método.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $null -eq $Collection.DoesNotExist
True
PS> $Collection.DoesNotExist()
InvalidOperation: Method invocation failed because [System.String] does not
contain a method named 'DoesNotExist'.
Dado que el objeto de colección no tiene el miembro, PowerShell enumera los elementos de la colección. Tenga en cuenta que el error MethodNotFound de especifica que System.String no contiene el método en vez de System.Collections.Generic.List.
Cuando se usa el operador de acceso a miembros para tener acceso a un método en un objeto de colección que no tiene el método y solo algunos elementos de la colección lo tienen, el comando devuelve un error de MethodNotFound
para el primer elemento de la colección que no tiene el método. Aunque se llame al método en algunos elementos, el comando solo devuelve el error.
PS> @('a', 1, 'c').ToUpper()
InvalidOperation: Method invocation failed because [System.Int32] does not
contain a method named 'ToUpper'.
Cuando se usa el operador de acceso a miembros para tener acceso a una propiedad en un objeto de colección que no tiene la propiedad y solo algunos elementos de la colección la tienen, el comando devuelve el valor de la propiedad de cada elemento de la colección que tiene la propiedad.
PS> $CapitalizedProperty = @{
MemberType = 'ScriptProperty'
Name = 'Capitalized'
Value = { $this.ToUpper() }
PassThru = $true
}
PS> [System.Collections.Generic.List[object]]$MixedCollection = @(
'a'
('b' | Add-Member @CapitalizedProperty)
('c' | Add-Member @CapitalizedProperty)
'd'
)
PS> $MixedCollection.Capitalized
B
C
Cuando una colección enumerable contiene una colección anidada, la enumeración de acceso a miembros se aplica a cada colección anidada.
Por ejemplo, $a
es una matriz que contiene dos elementos: una matriz anidada de cadenas y una sola cadena.
# Get the count of items in the array.
PS> $a.Count
2
# Get the count of items in each nested item.
PS> $a.GetEnumerator().Count
2
1
# Call the ToUpper() method on all items in the nested array.
PS> $a = @(, ('bar', 'baz'), 'foo')
PS> $a.ToUpper()
BAR
BAZ
FOO
Cuando se usa el operador de acceso a miembros, PowerShell enumera los elementos de $a
y llama al método ToUpper()
en todos los elementos.
Como se indicó anteriormente, puede haber diferencias sutiles de comportamiento y rendimiento entre los distintos métodos de enumeración.
Cuando la enumeración de acceso a miembros se interrumpe debido a un error, no se devuelve la salida de llamadas de métodos anteriores que fueron correctas. Las condiciones de error de terminación incluyen:
- el objeto enumerado carece del método al que se tiene acceso
- el método al que se accede genera un error de terminación
Considere el ejemplo siguiente:
class Class1 { [object] Foo() { return 'Bar' } }
class Class2 { [void] Foo() { throw 'Error' } }
class Class3 {}
$example1 = ([Class1]::new(), [Class1]::new())
$example2 = ([Class1]::new(), [Class2]::new())
$example3 = ([Class1]::new(), [Class3]::new())
Ambos elementos de $example1
tienen el método Foo()
, por lo que la llamada al método se realiza correctamente.
PS> $example1.Foo()
Bar
Bar
El método Foo()
en el segundo elemento de $example2
produce un error, por lo que se produce un error en la enumeración.
PS> $example2.Foo()
Exception:
Line |
2 | class Class2 { [void] Foo() { throw 'Error' } }
| ~~~~~~~~~~~~~
| Error
El segundo elemento de $example2
no tiene el método Foo()
, por lo que se produce un error en la enumeración.
PS> $example3.Foo()
InvalidOperation: Method invocation failed because [Class3] does not contain
a method named 'Foo'.
Compare esto con la enumeración mediante ForEach-Object
PS> $example2 | ForEach-Object -MemberName Foo
Bar
ForEach-Object: Exception calling "Foo" with "0" argument(s): "Error"
PS> $example3 | ForEach-Object -MemberName Foo
Bar
Tenga en cuenta que el resultado muestra la llamada exitosa a Foo()
en el primer elemento de la matriz.
Si la colección de objetos contiene instancias de elementos de PSCustomObject, PowerShell devuelve inesperadamente valores $null
cuando falta la propiedad a la que se intenta acceder.
En los ejemplos siguientes, al menos un objeto tiene la propiedad a la que se hace referencia.
PS> $foo = [pscustomobject]@{ Foo = 'Foo' }
PS> $bar = [pscustomobject]@{ Bar = 'Bar' }
PS> $baz = [pscustomobject]@{ Baz = 'Baz' }
PS> ConvertTo-Json ($foo, $bar, $baz).Foo
[
"Foo",
null,
null
]
PS> ConvertTo-Json ((Get-Process -Id $PID), $foo).Name
[
"pwsh",
null
]
Se espera que PowerShell devuelva un único objeto para el elemento que tiene la propiedad especificada. Por el contrario, PowerShell también devuelve un valor de $null
para cada elemento que no tiene la propiedad.
Para obtener más información sobre este comportamiento, consulte Problema de PowerShell 13752.
Comentarios de PowerShell
PowerShell es un proyecto de código abierto. Seleccione un vínculo para proporcionar comentarios: