Condividi tramite


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.

Vedi anche