Partilhar via


about_Member-Access_Enumeration

Breve descrição

Descreve a enumeração automática de coleções ao usar o operador member-access.

Descrição longa

O PowerShell mantém uma lista de tipos enumeráveis. A partir do PowerShell 3.0, o recurso de enumeração de acesso de membro melhora a conveniência de usar o operador de acesso de membro (.) em objetos de coleção que são enumeráveis.

A enumeração de acesso de membro ajuda você a escrever código mais simples e mais curto. Em vez de canalizar um objeto de coleção para ForEach-Object ou usar o ForEach()método intrínseco para acessar membros em cada item da coleção, você pode usar o operador member-access no objeto de coleção.

Os exemplos a seguir produzem os mesmos resultados. O último exemplo demonstra o uso do operador member-access:

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

Você pode usar o operador de acesso de membro para obter os valores de uma propriedade em itens de uma coleção, mas não pode usá-lo para defini-los diretamente. Para obter mais informações, consulte about_Arrays. A enumeração de acesso de membro é um recurso de conveniência. Pode haver diferenças sutis de comportamento e desempenho entre os vários métodos de enumeração.

Quando você usa o operador member-access em um objeto e o membro especificado existe nesse objeto, o membro é invocado. Quando você usa o operador de acesso de membro em um objeto de coleção que não tem o membro especificado, o PowerShell enumera os itens nessa coleção e usa o operador de acesso de membro em cada item enumerado.

Durante a enumeração de acesso de membro para uma propriedade, o operador retorna o valor da propriedade para cada item que tem essa propriedade. Se nenhum item tiver a propriedade especificada, o operador retornará $null.

Durante a enumeração de acesso de membro para um método, o operador tenta chamar o método em cada item da coleção. Se qualquer item na coleção não tiver o método especificado, o operador retornará a exceção MethodNotFound .

Aviso

Durante a enumeração de acesso de membro para um método, o método é chamado em cada item da coleção. Se o método que você está chamando fizer alterações, as alterações serão feitas para cada item da coleção. Se ocorrer um erro durante a enumeração, o método é chamado somente nos itens enumerados antes do erro. Para maior segurança, considere enumerar manualmente os itens e manipular explicitamente quaisquer erros.

Aceder aos membros de um objeto não enumerável

Quando você usa o operador de acesso de membro em um objeto que não é uma coleção enumerável, o PowerShell invoca o membro para retornar o valor da propriedade ou saída do método para esse objeto.

PS> $MyString = 'abc'
PS> $MyString.Length
3
PS> $MyString.ToUpper()
ABC

Quando você usa o operador de acesso de membro em um objeto não enumerável que não tem o membro, o PowerShell retorna para a propriedade ausente ou um erro de MethodNotFound para o método ausente.

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

Acessar membros de um objeto de coleção

Quando você usa o operador member-access em um objeto de coleção que tem o membro, ele sempre retorna o valor da propriedade ou o resultado do método para o objeto de coleção.

Acessar membros que existem na coleção, mas não seus itens

Neste exemplo, os membros especificados existem na coleção, mas não os itens nela.

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

Acessar membros que existem na coleção e seus itens

Neste exemplo, os membros especificados existem na coleção e nos itens nela. Compare os resultados dos comandos usando o operador member-access na coleção com os resultados do uso do member-access operator nos itens de coleção no ForEach-Object. Na coleção, o operador retorna o valor da propriedade ou o resultado do método para o objeto de coleção e não os itens nele.

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

As coleções que implementam a interface System.Collections.IDictionary , como HashTable e OrderedDictionary, têm um comportamento diferente. Quando você usa o operador de acesso de membro em um dicionário que tem uma chave com o mesmo nome de uma propriedade, ele retorna o valor da chave em vez do da propriedade.

Você pode acessar o valor da propriedade do objeto de dicionário com o membro intrínseco psbase. Por exemplo, se o nome da chave for keys e você quiser retornar a coleção das chaves HashTable , use esta sintaxe:

$hashtable.psbase.Keys

Aceder a membros que existem em todos os elementos de uma coleção, mas não no próprio elemento

Quando usa o operador de acesso a membro num objeto de coleção que não tem o membro, mas os itens que estão nele têm, o PowerShell enumera os itens na coleção e devolve para cada item o valor da propriedade ou o resultado do método.

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

Acessar membros que não existem na coleção ou em seus itens

Quando você usa o operador member-access em um objeto de coleção que não tem o membro e nem os itens nele, o comando retorna $null se você especificar uma propriedade ou um erro MethodNotFound se especificar um 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'.

Como o objeto de coleção não tem o membro, o PowerShell enumerou os itens na coleção. Observe que o erro MethodNotFound especifica que System.String não contém o método, em comparação com System.Collections.Generic.List.

Métodos de acesso que existem apenas em alguns itens de uma coleção

Quando você usa o operador member-access para acessar um método em um objeto de coleção que não tem o método e apenas alguns itens na coleção o têm, o comando retorna um erro MethodNotFound para o primeiro item da coleção que não tem o método. Mesmo que o método seja chamado em alguns itens, o comando retorna apenas o erro.

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

Acessar propriedades que existem apenas em alguns itens de uma coleção

Quando você usa o operador de acesso de membro para acessar uma propriedade em um objeto de coleção que não tem a propriedade e apenas alguns itens na coleção a têm, o comando retorna o valor da propriedade para cada item da coleção que tem a propriedade.

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

Aceder a membros de uma coleção aninhada

Quando uma coleção enumerável contém uma coleção aninhada, a enumeração de acesso de membro é aplicada a cada coleção aninhada.

Por exemplo, $a é uma matriz que contém dois elementos: uma matriz aninhada de cadeias de caracteres e uma única cadeia de caracteres.

# 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

Quando você usa o operador de acesso de membro, o PowerShell enumera os itens em $a e chama o método ToUpper() em todos os itens.

Observações

Como dito anteriormente, pode haver diferenças sutis de comportamento e desempenho entre os vários métodos de enumeração.

Erros resultam em perda na produção.

Quando a enumeração de acesso de membro é encerrada por um erro, a saída de chamadas de método bem-sucedidas anteriores não é retornada. As condições de erro de encerramento incluem:

  • o objeto enumerado não tem o método acessado
  • O método acessado gera um erro de encerramento

Considere o seguinte exemplo:

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 os itens no $example1 têm o método Foo(), portanto, a chamada de método é bem-sucedida.

PS> $example1.Foo()
Bar
Bar

O método Foo() no segundo item em $example2 gera um erro, portanto, a enumeração falha.

PS> $example2.Foo()
Exception:
Line |
   2 |  class Class2 { [void] Foo() { throw 'Error' } }
     |                                ~~~~~~~~~~~~~
     | Error

O segundo item em $example2 não tem o método Foo(), portanto, a enumeração falha.

PS> $example3.Foo()
InvalidOperation: Method invocation failed because [Class3] does not contain
a method named 'Foo'.

Compare isso com a enumeração usando 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 a saída mostra a chamada bem-sucedida executada para Foo() no primeiro item da matriz.

Coleções contendo instâncias PSCustomObject

Se a coleção de objetos contiver instâncias de itens PSCustomObject, o PowerShell inesperadamente retorna $null valores quando a propriedade acessada estiver ausente.

Nos exemplos a seguir, pelo menos um objeto tem a propriedade referenciada.

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
]

Você esperaria que o PowerShell retornasse um único objeto para o item que tem a propriedade especificada. Em vez disso, o PowerShell também retorna um valor $null para cada item que não tem a propriedade.

Para obter mais informações sobre esse comportamento, consulte PowerShell Issue #13752.

Consulte Também