Поделиться через


about_Member-Access_Enumeration

Краткое описание

Описывает автоматическое перечисление коллекций при использовании оператора доступа к членам.

Подробное описание

PowerShell поддерживает список типов, которые являются перечислимыми. Начиная с PowerShell 3.0, функция перечисления -члена повышает удобство использования оператора доступа к членам () для объектов коллекции, которые перечисляются.

Перечисление доступа к членам помогает создавать более простой и короткий код. Вместо того, чтобы отправлять объект ForEach-Object коллекции или использовать ForEach()встроенный метод для доступа к элементам в коллекции, можно использовать оператор доступа к члену в объекте коллекции.

В следующих примерах получаются одинаковые результаты. В последнем примере показано использование оператора доступа к члену:

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

Примечание.

Оператор доступа к членам можно использовать для получения значений свойства для элементов в коллекции, но его нельзя использовать для их прямого задания. Дополнительные сведения см. в about_Arrays. Перечисление доступа к членам — это удобная функция. Между различными методами перечисления могут быть тонкие различия в поведении и производительности.

При использовании оператора доступа к члену для объекта, и если указанный член существует в этом объекте, член активируется. При использовании оператора доступа к члену в объекте коллекции, который не имеет указанного элемента, PowerShell перечисляет элементы в этой коллекции и использует оператор доступа к членам для каждого перечисленного элемента.

Во время перечисления доступа к члену для свойства оператор возвращает значение свойства для каждого элемента, имеющего это свойство. Если у элементов нет указанного свойства, оператор возвращается $null.

Во время перечисления доступа к члену для метода оператор пытается вызвать метод для каждого элемента в коллекции. Если какой-либо элемент в коллекции не имеет указанного метода, оператор возвращает исключение MethodNotFound .

Предупреждение

Во время перечисления доступа к члену для метода метод вызывается для каждого элемента в коллекции. Если вызываемый метод вносит изменения, изменения вносятся для каждого элемента в коллекции. Если во время перечисления возникает ошибка, метод вызывается только в элементах, перечисленных до ошибки. Для дополнительной безопасности рекомендуется вручную перечислять элементы и явно обрабатывать любые ошибки.

Доступ к элементам неперечисляемого объекта

При использовании оператора доступа к члену в объекте, который не является перечисленной коллекцией, PowerShell вызывает элемент для возврата значения свойства или выходных данных метода для этого объекта.

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

При использовании оператора доступа к члену в неперечислимом объекте, в котором отсутствует член, PowerShell возвращает $null для отсутствующего свойства или ошибку MethodNotFound для отсутствующего метода.

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

Доступ к членам объекта коллекции

При использовании оператора доступа к члену в объекте коллекции с элементом всегда возвращается значение свойства или результат метода для объекта коллекции.

Доступ к членам, существующим в коллекции, но не к её элементам.

В этом примере указанные элементы существуют в коллекции, но не элементы в ней.

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

Доступ к членам, существующим в коллекции и её элементах

В этом примере указанные элементы существуют как в коллекции, так и в элементах. Сравните результаты команд с помощью оператора доступа к членам в коллекции с результатами использования оператора доступа к членам в элементах ForEach-Objectколлекции. В коллекции оператор возвращает значение свойства или результат метода для объекта коллекции, а не элементов в нем.

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

Примечание.

Коллекции, реализующие интерфейс System.Collections.IDictionary , такие как HashTable и OrderedDictionary, имеют другое поведение. При использовании оператора доступа к члену в словаре с тем же именем, что и свойство, он возвращает значение ключа вместо свойства.

Вы можете получить доступ к значению свойства объекта словаря с помощью встроенного элемента psbase. Например, если имя ключа и keys вы хотите вернуть коллекцию ключей HashTable , используйте следующий синтаксис:

$hashtable.psbase.Keys

Доступ к элементам, существующим во всех объектах коллекции, но не в самом объекте.

При использовании оператора доступа к члену на объекте коллекции, который сам не имеет данного члена, но элементы в нем имеют, PowerShell перечисляет элементы коллекции и возвращает значение свойства или результат метода для каждого элемента.

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

Доступ к членам, которые не существуют в коллекции или её элементах

Если вы используете оператор доступа к члену у объекта коллекции, у которого нет этого члена, и ни один из его элементов также не имеет, команда возвращает $null, если указано свойство, или ошибку MethodNotFound, если указан метод.

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

Поскольку у объекта коллекции нет члена, PowerShell перечислил элементы в коллекции. Обратите внимание, что ошибка MethodNotFound указывает, что System.String не содержит метод, а не System.Collections.Generic.List.

Методы доступа, которые существуют только для некоторых элементов в коллекции

При использовании оператора доступа к члену для доступа к методу в объекте коллекции, который не имеет метода, и только некоторые элементы в коллекции имеют его, команда возвращает ошибку MethodNotFound для первого элемента в коллекции, у которой нет метода. Несмотря на то, что метод вызывается для некоторых элементов, команда возвращает ошибку только.

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

Доступ к свойствам, которые существуют только в некоторых элементах коллекции

При использовании оператора доступа к члену для доступа к свойству объекта коллекции, который не имеет свойства, и только некоторые элементы в коллекции имеют его, команда возвращает значение свойства для каждого элемента коллекции, имеющего свойство.

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

Доступ к членам вложенной коллекции

Если перечисленная коллекция содержит вложенную коллекцию, перечисление доступа к членам применяется к каждой вложенной коллекции.

Например, $a представляет собой массив, содержащий два элемента: вложенный массив строк и одну строку.

# 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

При использовании оператора доступа к членам PowerShell перечисляет элементы в $a и вызывает метод ToUpper() для всех элементов.

Примечания

Как упоминалось ранее, между различными методами перечисления могут быть тонкие различия в поведении и производительности.

Ошибки приводят к потере выходных данных

Когда перечисление доступа к членам завершается ошибкой, выходные данные из предыдущих успешных вызовов методов не возвращаются. К конечным условиям ошибки относятся:

  • Перечисленный объект не имеет доступа к методу
  • Доступ к методу вызывает завершающееся сообщение об ошибке

Рассмотрим следующий пример:

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())

Оба элемента в $example1 имеют метод Foo(), поэтому вызов метода завершается успешно.

PS> $example1.Foo()
Bar
Bar

Метод Foo() во втором элементе в $example2 вызывает ошибку, поэтому перечисление завершается ошибкой.

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

У второго элемента в $example2 отсутствует метод Foo(), в результате чего процесс перечисления завершается ошибкой.

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

Сравните это с перечислением с помощью 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

Обратите внимание, что выходные данные показывают успешный вызов Foo() на первом элементе в массиве.

Коллекции, содержащие экземпляры PSCustomObject

Если коллекция объектов содержит экземпляры элементов PSCustomObject, PowerShell неожиданно возвращает значения $null при отсутствии доступного свойства.

В следующих примерах по крайней мере один объект имеет указанное свойство.

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
]

Вы ожидаете, что PowerShell вернет один объект для элемента с указанным свойством. Вместо этого PowerShell также возвращает значение $null для каждого элемента, у которых нет свойства.

Дополнительные сведения об этом поведении см. в статье о проблеме PowerShell #13752.

См. также