about_Member-Access_Enumeration
Descrizione breve
Descrive l'enumerazione automatica delle raccolte quando si usa l'operatore member-access.
Descrizione lunga
PowerShell gestisce un elenco di tipi enumerabili. A partire da PowerShell 3.0, la funzionalità di enumerazione di accesso ai membri migliora la praticità dell'uso dell'operatore di accesso ai membri (.
) sugli oggetti di raccolta enumerabili.
L'enumerazione Di accesso ai membri consente di scrivere codice più semplice e più breve. Anziché eseguire il piping di un oggetto raccolta a ForEach-Object
o utilizzando il ForEach()
metodo intrinseco per accedere ai membri di ogni elemento dell'insieme, è possibile utilizzare l'operatore di accesso ai membri nell'oggetto raccolta.
Gli esempi seguenti producono gli stessi risultati. L'ultimo esempio illustra l'uso dell'operatore 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
È possibile usare l'operatore di accesso ai membri per ottenere i valori di una proprietà sugli elementi di una raccolta, ma non è possibile usarli direttamente per impostarli direttamente. Per altre informazioni, vedere about_Arrays. L'enumerazione di accesso ai membri è una comoda funzionalità. Possono verificarsi lievi differenze di comportamento e prestazioni tra i vari metodi di enumerazione.
Quando si utilizza l'operatore di accesso ai membri in un oggetto e il membro specificato esiste su tale oggetto, viene richiamato il membro. Quando si usa l'operatore di accesso ai membri in un oggetto raccolta che non dispone del membro specificato, PowerShell enumera gli elementi della raccolta e usa l'operatore di accesso ai membri per ogni elemento enumerato.
Durante l'enumerazione di accesso ai membri per una proprietà, l'operatore restituisce il valore della proprietà per ogni elemento con tale proprietà. Se non sono presenti elementi con la proprietà specificata, l'operatore restituisce $null
.
Durante l'enumerazione di accesso ai membri per un metodo, l'operatore tenta di chiamare il metodo su ogni elemento della raccolta. Se un elemento della raccolta non dispone del metodo specificato, l'operatore restituisce l'eccezione MethodNotFound .
Avviso
Durante l'enumerazione di accesso ai membri per un metodo, il metodo viene chiamato su ogni elemento della raccolta. Se il metodo che si sta chiamando apporta modifiche, le modifiche vengono apportate per ogni elemento della raccolta. Se si verifica un errore durante l'enumerazione, il metodo viene chiamato solo sugli elementi enumerati prima dell'errore. Per maggiore sicurezza, è consigliabile enumerare manualmente gli elementi e gestire in modo esplicito eventuali errori.
Accedere ai membri di un oggetto non enumerabile
Quando si usa l'operatore di accesso ai membri in un oggetto che non è un insieme enumerabile, PowerShell richiama il membro per restituire il valore della proprietà o dell'output del metodo per tale oggetto.
PS> $MyString = 'abc'
PS> $MyString.Length
3
PS> $MyString.ToUpper()
ABC
Quando si usa l'operatore di accesso ai membri in un oggetto non enumerabile che non dispone del membro, PowerShell restituisce $null
per la proprietà mancante o un errore di MethodNotFound per il metodo mancante.
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
Accedere ai membri di un oggetto di raccolta
Quando si utilizza l'operatore di accesso ai membri in un oggetto raccolta con il membro, restituisce sempre il valore della proprietà o il risultato del metodo per l'oggetto raccolta.
Accedere ai membri presenti nella raccolta, ma non ai relativi elementi
In questo esempio i membri specificati esistono nella raccolta, ma non gli elementi in esso contenuti.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b')
PS> $Collection.IsReadOnly
False
PS> $Collection.Add('c')
PS> $Collection
a
b
c
Accedere ai membri esistenti nella raccolta e ai relativi elementi
Per questo esempio, i membri specificati esistono sia nella raccolta che negli elementi in esso contenuti. Confrontare i risultati dei comandi usando l'operatore member-access nella raccolta con i risultati dell'uso dell'operatore member-access sugli elementi della raccolta in ForEach-Object
. Nell'insieme l'operatore restituisce il valore della proprietà o il risultato del metodo per l'oggetto raccolta e non gli elementi in esso contenuti.
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
Le raccolte che implementano l'interfaccia System.Collections.IDictionary , ad esempio HashTable e OrderedDictionary, hanno un comportamento diverso. Quando si usa l'operatore di accesso ai membri in un dizionario con una chiave con lo stesso nome di una proprietà, restituisce il valore della chiave anziché quello della proprietà.
È possibile accedere al valore della proprietà dell'oggetto dizionario con il membro intrinseco psbase. Ad esempio, se il nome della chiave è keys
e si vuole restituire la raccolta delle chiavi HashTable , usare questa sintassi:
$hashtable.psbase.Keys
Accedere ai membri esistenti in tutti gli elementi di una raccolta, ma non all'elemento stesso
Quando si usa l'operatore di accesso ai membri in un oggetto di raccolta che non ha il membro, ma gli elementi in essa lo hanno, PowerShell enumera gli elementi nella raccolta e restituisce il valore della proprietà o il risultato del metodo per ogni elemento.
PS> [System.Collections.Generic.List[string]]$Collection = @('a', 'b', 'c')
PS> $Collection.Length
1
1
1
PS> $Collection.ToUpper()
A
B
C
Accedere ai membri che non esistono nella raccolta o nei relativi elementi
Quando si utilizza l'operatore di accesso ai membri su un oggetto raccolta che non ha il membro e né gli elementi al suo interno, il comando restituisce $null
se si specifica una proprietà o un errore MethodNotFound
se si specifica un metodo.
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'.
Poiché la raccolta non contiene il membro, PowerShell ha enumerato gli elementi nella raccolta. Si noti che l'errore MethodNotFound specifica che System.String non contiene il metodo anziché System.Collections.Generic.List.
Metodi di accesso esistenti solo in alcuni elementi di una raccolta
Quando si utilizza l'operatore di accesso dei membri per richiamare un metodo su un oggetto di collezione che non possiede il metodo, ma solo alcuni elementi della collezione lo hanno, il comando restituisce un errore MethodNotFound
per il primo elemento della collezione che non possiede il metodo. Anche se il metodo viene chiamato su alcuni elementi, il comando restituisce solo l'errore.
PS> @('a', 1, 'c').ToUpper()
InvalidOperation: Method invocation failed because [System.Int32] does not
contain a method named 'ToUpper'.
Accedere alle proprietà esistenti solo in alcuni elementi di una raccolta
Quando si utilizza l'operatore di accesso ai membri per accedere a una proprietà su un oggetto raccolta che di per sé non dispone della proprietà, mentre solo alcuni elementi nell'insieme la possiedono, il comando restituisce il valore della proprietà per ogni elemento dell'insieme che la possiede.
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
Accedere ai membri di una raccolta annidata
Quando una raccolta enumerabile contiene una raccolta nidificata, l'enumerazione di accesso ai membri viene applicata a ogni raccolta nidificata.
Ad esempio, $a
è una matrice contenente due elementi: una matrice nidificata di stringhe e una singola stringa.
# 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 si usa l'operatore di accesso ai membri, PowerShell enumera gli elementi in $a
e chiama il metodo ToUpper()
su tutti gli elementi.
Note
Come indicato in precedenza, possono verificarsi lievi differenze di comportamento e prestazioni tra i vari metodi di enumerazione.
Gli errori generano un output perso
Quando l'enumerazione di accesso ai membri viene terminata da un errore, l'output delle precedenti chiamate di metodo riuscite non viene restituito. Le condizioni di errore irreversibili includono:
- L'oggetto enumerato non dispone del metodo a cui si accede
- Il metodo a cui si accede solleva un errore fatale
Si consideri l'esempio seguente:
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())
Entrambi gli elementi in $example1
hanno il metodo Foo()
, quindi la chiamata al metodo ha esito positivo.
PS> $example1.Foo()
Bar
Bar
Il metodo Foo()
sul secondo elemento in $example2
genera un errore, quindi l'enumerazione ha esito negativo.
PS> $example2.Foo()
Exception:
Line |
2 | class Class2 { [void] Foo() { throw 'Error' } }
| ~~~~~~~~~~~~~
| Error
Il secondo elemento in $example2
non dispone del metodo Foo()
, quindi l'enumerazione ha esito negativo.
PS> $example3.Foo()
InvalidOperation: Method invocation failed because [Class3] does not contain
a method named 'Foo'.
Confronta questo con un'enumerazione 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
Si noti che l'output mostra la chiamata riuscita a Foo()
sul primo elemento dell'array.
Raccolte contenenti istanze di PSCustomObject
Se la raccolta di oggetti contiene istanze di elementi PSCustomObject, PowerShell restituisce inaspettatamente $null
valori quando la proprietà a cui si accede è mancante.
Negli esempi seguenti almeno un oggetto ha la proprietà a cui si fa riferimento.
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
]
Si prevede che PowerShell restituisca un singolo oggetto per l'elemento con la proprietà specificata. PowerShell restituisce invece anche un valore $null
per ogni elemento che non ha la proprietà .
Per altre informazioni su questo comportamento, vedere Problema di PowerShell #13752.