about_Member-Access_Enumeration
Krótki opis
Opisuje automatyczne wyliczanie kolekcji podczas korzystania z operatora dostępu do składowych.
Długi opis
Program PowerShell utrzymuje listę typów, które są wyliczane. Począwszy od PowerShell 3.0, funkcja wyliczania dostępu do elementu członkowskiego
Wyliczenie dostępu do składowych ułatwia pisanie prostszego i krótszego kodu. Zamiast potokować obiekt kolekcji do obiektu kolekcji lub używając ForEach-Object
ForEach()
wewnętrznej w celu uzyskania dostępu do elementów członkowskich w każdej kolekcji, można użyć operatora dostępu do elementu członkowskiego w obiekcie kolekcji.
W poniższych przykładach przedstawiono te same wyniki. W ostatnim przykładzie pokazano użycie operatora dostępu członka:
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
Uwaga
Możesz użyć operatora dostępu do elementu członkowskiego, aby pobrać wartości właściwości w elementach w kolekcji, ale nie można jej użyć do ich bezpośredniego ustawienia. Aby uzyskać więcej informacji, zobacz about_Arrays. Wyliczanie dostępu do elementów składowych jest funkcją ułatwiającą życie. Mogą istnieć subtelne zachowania i różnice wydajności między różnymi metodami wyliczania.
Jeśli używasz operatora dostępu do członka w obiekcie i określony członek istnieje w tym obiekcie, jest on wywoływany. Jeśli używasz operatora dostępu do składowej w obiekcie kolekcji, który nie ma określonej składowej, program PowerShell wylicza elementy w tej kolekcji i używa operatora dostępu do składowej w każdym wyliczonym elemencie.
Podczas wyliczania dostępu do elementu członkowskiego dla właściwości operator zwraca wartość właściwości dla każdego elementu, który ma ta właściwość. Jeśli żadne elementy nie mają określonej właściwości, operator zwraca wartość $null
.
Podczas wyliczania dostępu do elementu członkowskiego dla metody operator próbuje wywołać metodę dla każdego elementu w kolekcji. Jeśli którykolwiek element w kolekcji nie ma określonej metody, operator zwraca wyjątek MethodNotFound .
Ostrzeżenie
Podczas wyliczania dostępu do składowych dla metody metoda jest wywoływana dla każdego elementu w kolekcji. Jeśli wywoływana metoda wprowadza zmiany, zmiany są wprowadzane dla każdego elementu w kolekcji. Jeśli podczas wyliczania wystąpi błąd, metoda jest wywoływana tylko na elementach wyliczonych przed błędem. Aby uzyskać dodatkowe bezpieczeństwo, rozważ ręczne wyliczanie elementów i jawne obsługiwanie błędów.
Dostęp do składników obiektu nienumerowalnego
Jeśli używasz operatora dostępu do elementu członkowskiego w obiekcie, który nie jest kolekcją wyliczalną, program PowerShell wywołuje element członkowski w celu zwracania wartości właściwości lub danych wyjściowych metody dla tego obiektu.
PS> $MyString = 'abc'
PS> $MyString.Length
3
PS> $MyString.ToUpper()
ABC
Jeśli używasz operatora dostępu do elementu członkowskiego w obiekcie nieliczalnym, który nie ma elementu członkowskiego, program PowerShell zwraca $null
dla brakującej właściwości lub błąd MethodNotFound dla brakującej metody.
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'.
Uzyskiwanie dostępu do elementów obiektu kolekcji
Jeśli używasz operatora dostępu do elementu członkowskiego w obiekcie kolekcji, który ma element członkowski, zawsze zwraca wartość właściwości lub wynik metody dla obiektu kolekcji.
Uzyskaj dostęp do członków, którzy istnieją w kolekcji, ale nie są jej elementami.
W tym przykładzie określone elementy członkowskie istnieją w kolekcji, ale nie w niej.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b')
PS> $Collection.IsReadOnly
False
PS> $Collection.Add('c')
PS> $Collection
a
b
c
Dostęp do członków istniejących w ramach kolekcji oraz jej składników
W tym przykładzie określone elementy członkowskie istnieją zarówno w kolekcji, jak i w niej elementach. Porównaj wyniki poleceń przy użyciu operatora dostępu elementu członkowskiego w kolekcji do wyników przy użyciu operatora dostępu do elementu członkowskiego w elementach kolekcji w ForEach-Object
programie . W kolekcji operator zwraca wartość właściwości lub wynik metody dla obiektu kolekcji, a nie elementy w nim.
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
Uwaga
Kolekcje implementujące interfejs System.Collections.IDictionary , takie jak HashTable i OrderedDictionary, mają inne zachowanie. Jeśli używasz operatora dostępu do elementu członkowskiego w słowniku, który ma klucz o takiej samej nazwie jak właściwość, zwraca wartość klucza zamiast właściwości.
Dostęp do wartości właściwości obiektu słownika można uzyskać za pomocą wewnętrznego elementu członkowskiego psbase. Jeśli na przykład nazwa klucza to keys
i chcesz zwrócić kolekcję kluczy HashTable , użyj następującej składni:
$hashtable.psbase.Keys
Dostęp do elementów, które istnieją we wszystkich elementach w kolekcji, ale nie w nim samym
Jeśli używasz operatora dostępu do elementu członkowskiego w obiekcie kolekcji, który nie ma elementu członkowskiego, ale elementy go mają, PowerShell przegląda elementy w kolekcji i zwraca wartość właściwości lub wynik metody dla każdego z nich.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $Collection.Length
1
1
1
PS> $Collection.ToUpper()
A
B
C
Dostęp do części, które nie istnieją w kolekcji lub jej elementach
Jeśli używasz operatora dostępu do składowych w obiekcie kolekcji, który nie ma składowej i żadna z jego pozycji również jej nie posiada, polecenie zwraca $null
, jeśli określisz właściwość albo błąd MethodNotFound
, jeśli określisz metodę.
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'.
Ponieważ obiekt kolekcji nie ma elementu członkowskiego, program PowerShell wyliczał elementy w kolekcji. Zauważ, że błąd MethodNotFound określa, że System.String nie zawiera metody zamiast System.Collections.Generic.List.
Metody dostępu, które istnieją tylko w niektórych elementach w kolekcji
Jeśli używasz operatora dostępu do członków, aby uzyskać dostęp do metody w obiekcie kolekcji, który jej nie posiada, a tylko niektóre elementy w kolekcji ją mają, polecenie zwraca błąd MethodNotFound
dla pierwszego elementu w kolekcji, który nie ma tej metody. Mimo że metoda jest wywoływana dla niektórych elementów, polecenie zwraca tylko błąd.
PS> @('a', 1, 'c').ToUpper()
InvalidOperation: Method invocation failed because [System.Int32] does not
contain a method named 'ToUpper'.
Dostęp do właściwości, które istnieją tylko dla niektórych elementów w kolekcji
Jeśli używasz operatora dostępu do członków, aby uzyskać dostęp do właściwości w obiekcie kolekcji, który jej nie posiada, a tylko niektóre elementy w kolekcji ją mają, polecenie zwraca wartość właściwości dla każdego elementu w kolekcji, który ma tę właściwość.
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
Uzyskiwanie dostępu do elementów zagnieżdżonej kolekcji
Gdy kolekcja wyliczalna zawiera zagnieżdżone kolekcje, enumeracja dostępu do elementów jest stosowana do każdej zagnieżdżonej kolekcji.
Na przykład $a
to tablica zawierająca dwa elementy: zagnieżdżoną w sobie tablicę ciągów i pojedynczy ciąg.
# 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
W przypadku korzystania z operatora dostępu do składowych PowerShell wylicza elementy w $a
i wywołuje metodę ToUpper()
dla wszystkich elementów.
Notatki
Jak wspomniano wcześniej, mogą istnieć subtelne zachowania i różnice wydajności między różnymi metodami wyliczania.
Błędy powodują utratę danych wyjściowych
Jeśli wyliczanie dostępu do elementu członkowskiego zostanie przerwane przez błąd, dane wyjściowe z wcześniejszych pomyślnych wywołań metod nie zostaną zwrócone. Warunki błędu zakończenia obejmują:
- wyliczony obiekt nie ma metody dostępnej
- metoda, do której uzyskano dostęp, zgłasza błąd krytyczny
Rozważmy następujący przykład:
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())
Oba elementy w $example1
mają metodę Foo()
, więc wywołanie metody powiedzie się.
PS> $example1.Foo()
Bar
Bar
Metoda Foo()
w drugim elemencie w $example2
zgłasza błąd, więc wyliczenie kończy się niepowodzeniem.
PS> $example2.Foo()
Exception:
Line |
2 | class Class2 { [void] Foo() { throw 'Error' } }
| ~~~~~~~~~~~~~
| Error
Drugi element w $example2
nie ma metody Foo()
, więc wyliczenie kończy się niepowodzeniem.
PS> $example3.Foo()
InvalidOperation: Method invocation failed because [Class3] does not contain
a method named 'Foo'.
Porównaj to z wyliczeniem przy użyciu 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
Zwróć uwagę, że dane wyjściowe pokazują pomyślne wywołanie Foo()
na pierwszym elemencie w tablicy.
Kolekcje zawierające wystąpienia obiektu PSCustomObject
Jeśli kolekcja obiektów zawiera wystąpienia elementów PSCustomObject, program PowerShell nieoczekiwanie zwraca $null
wartości, gdy brakuje dostępnej właściwości.
W poniższych przykładach co najmniej jeden obiekt ma przywołyną właściwość.
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
]
Oczekuje się, że program PowerShell zwróci pojedynczy obiekt dla elementu, który ma określoną właściwość. Zamiast tego program PowerShell zwraca również wartość $null
dla każdego elementu, który nie ma właściwości.
Aby uzyskać więcej informacji na temat tego zachowania, zobacz Problem z programem PowerShell #13752.