Uno degli obiettivi principali di PowerShell è quello di fornire all’utente un ambiente di scripting coerente e facile da usare; d’altra parte, poiché gli oggetti della shell fanno parte dell’ecosistema di classi di Microsoft .NET, talvolta questa coerenza potrebbe sembrare difficile da perseguire.
In questo snippet si esamina un operatore di PowerShell in grado di rendere coerente l'interazione con collezioni di oggetti e singole istanze, illustrandone la sintassi ed alcuni esempi d'uso.
L’output della maggior parte dei cmdlet consiste in una collezione di oggetti di un qualche tipo, su cui è possibile interagire tramite i membri comuni a tutte le collezioni che derivano da System.Array; nello script che segue, ad esempio, si impiega la proprietà Length di System.Array per recuperare il numero di file e cartelle il cui nome inizia con la lettera d, presenti nel percorso corrente:
<pre>PS C:\Users\Ikmju> (Get-ChildItem d*).Length
3</pre>
Nel caso in cui il cmdlet emetta un unico oggetto, tuttavia, la shell non considera più una collezione di elementi ma permette di lavorare sull’oggetto stesso; lo script che segue, ad esempio, permette di recuperare l’estensione di un determinato file utilizzando il cmdlet osservato in precedenza:
<pre>PS C:\Users\Ikmju> (Get-ChildItem .\test.txt).Extension
.txt</pre>
Come il lettore può intuire, questa maggiore libertà di espressione potrebbe celare errori difficili da riconoscere, che si basano sull’assunto che l’output di un comando sia una collezione oppure meno. Se il percorso specificato nel primo script tramite caratteri wildcard avesse individuato un unico elemento di tipo file, ad esempio, la proprietà Length avrebbe ritornato non il numero di elementi della collezione ma la dimensione del file stesso!
<pre>PS C:\Users\Ikmju> (Get-ChildItem d*.txt).Length
783</pre>
Per ovviare a questo tipo di problema, a partire da PowerShell 2.0 è disponibile l’operatore di sottoespressione di array, chiamato spesso operatore splat, che consente di convertire automaticamente qualsiasi espressione in un array. Utilizzando questo operatore, dunque, è possibile considerare l’output di un qualsiasi cmdlet (o di una qualsiasi istruzione, in generale) come se fosse sempre una collezione: nel caso vi sia un unico elemento l’operatore ritorna una collezione con l’elemento specificato, mentre nel caso l’espressione sia già una collezione l’operatore ne ritorna il riferimento, senza operare alcuna modifica. Nel caso, infine, in cui l’espressione fornita non contenga alcun oggetto, l’operatore ritorna una collezione vuota.
L’operatore di sotto-espressione di array è individuato dal simbolo di a commerciale (@) e, come mostra questo schema, segue una sintassi molto semplice:
Applicando l’operatore splat allo script illustrato in precedenza, dunque, è possibile rendere più coerente il codice e forzare la shell ad impiegare una collezione in qualsiasi caso, a prescindere dall’output del comando invocato. Come si può constatare, infatti, in questo caso lo script estrae correttamente il numero di elementi che corrispondono alla ricerca effettuata:
<pre>PS C:\Users\Ikmju> @(Get-ChildItem d*.txt).Length
1</pre>
D’altra parte, applicando l’operatore al primo script il risultato non cambia:
<pre>PS C:\Users\Ikmju> @(Get-ChildItem d*).Length
3</pre>
Quando il caso lo richiede, dunque, conviene sempre utilizzare l’operatore di sotto-espressione di array a fronte dell’output dei comandi che si invocano.