Leer en inglés

Compartir a través de


about_Member-Access_Enumeration

Descripción breve

Describe la enumeración automática de colecciones al usar el operador de acceso a miembros.

Descripción larga

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:

PowerShell
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.

Acceso a miembros de un objeto no enumerable

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.

PowerShell
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.

PowerShell
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'.

Acceso a miembros de un objeto de colección

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.

Acceso a miembros que existen en la colección, pero no a sus elementos

En este ejemplo, los miembros especificados existen en la colección, pero no los elementos que la componen.

PowerShell
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b')
PS> $Collection.IsReadOnly
False
PS> $Collection.Add('c')
PS> $Collection
a
b
c

Acceso a los miembros que existen en la colección y a sus elementos

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.

PowerShell
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:

PowerShell
$hashtable.psbase.Keys

Acceda a miembros que existen en todos los elementos de una colección pero no en ella misma

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.

PowerShell
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $Collection.Length
1
1
1
PS> $Collection.ToUpper()
A
B
C

Acceso a miembros que no existen en la colección o a sus elementos

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.

PowerShell
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.

Acceso a métodos que solo existen en algunos elementos de una colección

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.

PowerShell
PS> @('a', 1, 'c').ToUpper()
InvalidOperation: Method invocation failed because [System.Int32] does not
contain a method named 'ToUpper'.

Acceso a propiedades que solo existen en algunos elementos de una colección

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.

PowerShell
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

Acceso a los miembros de una colección anidada

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.

PowerShell
# 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.

Notas

Como se indicó anteriormente, puede haber diferencias sutiles de comportamiento y rendimiento entre los distintos métodos de enumeración.

Los errores resultan en pérdida de producció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:

PowerShell
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.

PowerShell
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.

PowerShell
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.

PowerShell
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

PowerShell
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.

Colecciones que contienen instancias de PSCustomObject

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.

PowerShell
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.

Consulte también