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 de acceso a miembros le ayuda a escribir código más sencillo y más corto. En lugar de canalización de un objeto de colección a ForEach-Object o mediante el ForEach()método intrínseco para tener acceso a los miembros de cada elemento de la colección, puede usar 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 de miembro para una propiedad, el operador devuelve el valor de la propiedad para cada elemento que tiene esa propiedad. Si ningún elemento tiene la propiedad especificada, el operador devuelve $null.

Durante la enumeración de acceso a miembros de 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 de 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 realizan para cada elemento de la colección. Si se produce un error durante la enumeración, solo se llama al método en los elementos enumerados antes del error. Para mayor seguridad, considere la posibilidad de enumerar manualmente los elementos y controlar explícitamente los errores.

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.

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()
Method invocation failed because [System.String] does not contain a method named 'DoesNotExist'.
At line:1 char:1
+ $MyString.DoesNotExist()
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

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 en los elementos que contiene.

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 en la colección y en los elementos de él. 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 la 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 de ella.

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 usa el operador de acceso a miembros 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 tener acceso al valor de propiedad del objeto de diccionario con el miembro intrínseco psbase. Por ejemplo, si el nombre de clave es keys y desea devolver la colección de claves hashTable , use esta sintaxis:

$hashtable.psbase.Keys

Acceder a miembros que existen en todos los elementos de una colección pero no en la colección 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.

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 usas el operador de acceso de miembro en un objeto de colección que no tiene el miembro ni los elementos en él, el comando devuelve $null si especificas una propiedad o un error MethodNotFound si especificas 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. Observe que el error MethodNotFound especifica que System.String no contiene el método sino 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 llama 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'.

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.

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.

# 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 provocan una pérdida de resultados

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

Observe que los resultados muestran la llamada exitosa a Foo() en el primer elemento del arreglo.

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.

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