about_Member-Access_Enumeration
Krátký popis
Popisuje automatický výčet kolekcí při použití operátoru přístupu člena.
Dlouhý popis
PowerShell udržuje seznam typů, které jsou výčtové. Počínaje PowerShellem 3.0 funkce pro výčet přístupu k členům zvyšuje pohodlí při používání operátoru přístupu k členovi (.
) u objektů kolekce, které lze vyjmenovat.
Výčet přístupu členů vám pomůže psát jednodušší a kratší kód. Místo propojení objektu ForEach-Object
kolekce nebo použití ForEach()
vnitřní metody pro přístup ke členům u každé položky v kolekci můžete použít operátor přístupu člena v objektu kolekce.
Následující příklady vytvoří stejné výsledky. Poslední příklad ukazuje použití operátoru přístupu člena:
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
Poznámka:
Pomocí operátoru přístupu člena můžete získat hodnoty vlastnosti u položek v kolekci, ale nemůžete ho použít k jejich přímému nastavení. Další informace najdete v tématu about_Arrays. Výčet přístupu členů je funkce usnadnění. Mezi různými metodami výčtu mohou být drobné rozdíly v chování a výkonu.
Pokud pro objekt použijete operátor přístupu člena a zadaný člen v tomto objektu existuje, je vyvolán člen. Pokud použijete operátor přístupu člena u objektu kolekce, který nemá zadaný člen, PowerShell vytvoří výčet položek v této kolekci a použije operátor přístupu člena pro každou položku výčtu.
Během výčtu přístupu člena pro vlastnost vrátí operátor hodnotu vlastnosti pro každou položku, která má tuto vlastnost. Pokud žádné položky nemají zadanou vlastnost, vrátí operátor hodnotu $null
.
Během výčtu přístupu člena pro metodu se operátor pokusí volat metodu pro každou položku v kolekci. Pokud některá položka v kolekci nemá zadanou metodu, vrátí operátor výjimku MethodNotFound .
Upozorňující
Během výčtu přístupu člena pro metodu je volána metoda pro každou položku v kolekci. Pokud metoda, kterou voláte, provede změny pro každou položku v kolekci. Pokud dojde k chybě během výčtu, metoda je volána pouze u položek výčtu před chybou. Pokud chcete větší bezpečnost, zvažte ruční výčet položek a explicitně zpracovávat případné chyby.
Přístup k členům objektu bez výčtu
Pokud použijete operátor člen-přístup k objektu, který není výčtovou kolekcí, PowerShell vyvolá člena, který vrátí hodnotu vlastnosti nebo výstupu metody pro daný objekt.
PS> $MyString = 'abc'
PS> $MyString.Length
3
PS> $MyString.ToUpper()
ABC
Pokud použijete operátor přístupu člena u nevyčlenitelného objektu, který nemá daného člena, PowerShell vrátí $null
pro chybějící vlastnost nebo chybu MethodNotFound pro chybějící metodu.
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'.
Přístup k členům objektu kolekce
Pokud použijete operátor člen-přístup u objektu kolekce, který má člen, vrátí vždy hodnotu vlastnosti nebo výsledek metody pro objekt kolekce.
Přístup k členům, kteří existují v kolekci, ale ne její položky
V tomto příkladu existují zadané členy v kolekci, ale ne položky v ní.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b')
PS> $Collection.IsReadOnly
False
PS> $Collection.Add('c')
PS> $Collection
a
b
c
Přístupové členy, které existují v kolekci a jejích položkách
V tomto příkladu existují zadané členy v kolekci i v položkách v něm. Porovnejte výsledky příkazů pomocí operátoru přístupu člena v kolekci k výsledkům z použití operátoru přístupu člena u položek kolekce v ForEach-Object
. V kolekci vrátí operátor hodnotu vlastnosti nebo výsledek metody pro objekt kolekce, a ne položky v něm.
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
Poznámka:
Kolekce, které implementují rozhraní System.Collections.IDictionary , například HashTable a OrderedDictionary, mají jiné chování. Pokud použijete operátor přístupu člena ve slovníku, který má klíč se stejným názvem jako vlastnost, vrátí hodnotu klíče místo vlastnosti.
K hodnotě vlastnosti objektu slovníku se dostanete pomocí vnitřního člena psbase. Pokud je keys
například název klíče a chcete vrátit kolekci klíčů HashTable , použijte tuto syntaxi:
$hashtable.psbase.Keys
Přistupte k členům, které existují u všech položek v kolekci, ale ne u jednotlivých položek samých.
Pokud použijete operátor přístupu člena na objekt kolekce, který nemá daného člena, ale položky v něm ano, PowerShell nejprve vytvoří výčet položek v kolekci a poté vrátí hodnotu vlastnosti nebo výsledek metody pro každou položku.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $Collection.Length
1
1
1
PS> $Collection.ToUpper()
A
B
C
Přístupové členy, kteří neexistují v kolekci nebo jejích položkách
Pokud použijete operátor přístupu člena u objektu kolekce, který nemá člena a ani položky v něm, příkaz vrátí $null
pokud zadáte vlastnost nebo MethodNotFound
chybu, pokud zadáte metodu.
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'.
Vzhledem k tomu, že objekt kolekce nemá člena, PowerShell vyčíslil položky v kolekci. Všimněte si, že chyba MethodNotFound určuje, že System.String neobsahuje metodu, nikoli System.Collections.Generic.List.
Přístupové metody, které existují pouze u některých položek v kolekci
Pokud použijete operátor přístupu člena pro přístup k metodě u objektu kolekce, který nemá metodu a pouze některé položky v kolekci ji mají, příkaz vrátí chybu MethodNotFound
pro první položku v kolekci, která metodu nemá. I když se metoda volá u některých položek, příkaz vrátí pouze chybu.
PS> @('a', 1, 'c').ToUpper()
InvalidOperation: Method invocation failed because [System.Int32] does not
contain a method named 'ToUpper'.
Přístupové vlastnosti, které existují pouze u některých položek v kolekci
Když použijete operátor přístupu člena pro přístup k vlastnosti objektu kolekce, který vlastnost nemá a pouze některé položky v kolekci ji mají, příkaz vrátí hodnotu vlastnosti pro každou položku v kolekci, která má vlastnost.
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
Přístup ke členům vnořené kolekce
Pokud výčtová kolekce obsahuje vnořenou kolekci, použije se pro každou vnořenou kolekci výčet přístupu člena.
Například $a
je pole obsahující dva prvky: vnořené pole řetězců a jeden řetězec.
# 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
Pokud použijete operátor přístupu člena, PowerShell vytvoří výčet položek v $a
a zavolá metodu ToUpper()
pro všechny položky.
Poznámky
Jak jsme uvedli dříve, mezi různými metodami výčtu mohou být jemné rozdíly v chování a výkonu.
Chyby vedou ke ztrátě výstupu.
Pokud je výčet přístupu člena ukončen chybou, výstup z předchozích úspěšných volání metody se nevrátí. Mezi ukončující chybové stavy patří:
- výčtový objekt nemá přístupnou metodu.
- Přístupová metoda vyvolá ukončující chybu.
Podívejte se na následující příklad:
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())
Obě položky v $example1
mají metodu Foo()
, takže volání metody bude úspěšné.
PS> $example1.Foo()
Bar
Bar
Metoda Foo()
druhé položky v $example2
vyvolá chybu, takže výčet selže.
PS> $example2.Foo()
Exception:
Line |
2 | class Class2 { [void] Foo() { throw 'Error' } }
| ~~~~~~~~~~~~~
| Error
Druhá položka v $example2
nemá metodu Foo()
, takže výčet selže.
PS> $example3.Foo()
InvalidOperation: Method invocation failed because [Class3] does not contain
a method named 'Foo'.
Porovnejte to s výčtem pomocí 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
Všimněte si, že výstup ukazuje úspěšné volání Foo()
u první položky v poli.
Kolekce obsahující instance PSCustomObject
Pokud kolekce objektů obsahuje instance PSCustomObject položek, PowerShell neočekávaně vrací $null
hodnoty, když chybí přistupová vlastnost.
V následujících příkladech má alespoň jeden objekt odkazovanou vlastnost.
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
]
Očekáváte, že PowerShell vrátí jeden objekt pro položku, která má zadanou vlastnost. Místo toho PowerShell vrátí také hodnotu $null
pro každou položku, která vlastnost nemá.
Další informace o tomto chování najdete v tématu Problém s PowerShellem #13752.