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.
См. также
PowerShell