In powershell what does the syntax $x = . { ... } mean? How is it different from $x = @( ... ) From what I can tell they both create an array of the provided values but their output is slightly different.
I came across it in this script https://powershell.one/tricks/filesystem/filesystemwatcher when the author defines the handlers in the async example. Is there any significance to doing it that way? Other async examples for filewatcher use similar code.
$x = @(1,2,3)
$y = . {1,2,3}
@($x,$y) | foreach-object {
$_
$_.GetType()
}
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
1,2,3
True True Object[] System.Array
1
2
3
Non Trivial Example
$handlers = . {
Register-ObjectEvent -InputObject $watcher -EventName Changed -Action $Action
Register-ObjectEvent -InputObject $watcher -EventName Created -Action $Action
Register-ObjectEvent -InputObject $watcher -EventName Deleted -Action $Action
Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $Action
}
CodePudding user response:
In PowerShell what does the syntax
$x = . { ... }
mean?
{ ... }
is a Script Block which is used to store an expression..
is the dot sourcing operator, which can be used to execute a script block.
When put together, . { ... }
, the script block is executed as soon as it's interpreted by PowerShell.
How is it different from
$x = @( ... )
?
@( ... )
is the array subexpression operator, one of the ways you have to define aSystem.Array
in PowerShell.
For this particular case, I don't see a difference between both because your script block is storing a System.Array
and the dot sourcing operator doesn't change the return type of your expression.
However, when wrapping a sub-expression in @( .. )
you can ensure that the return will always be an array even if the sub-expression returns $null
:
@( $null ).GetType() # is an array
(. { $null }).GetType() # is an error
If you were to use the .Invoke()
method to execute the script block, the difference would've been the return type, from System.Array
to Collection`1
:
({1, 2, 3}.Invoke()).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Collection`1 System.Object
As for the linked code, the author is wrapping multiple calls to Register-ObjectEvent
inside the script block and executing it, there is no difference either because there are multiple calls to the cmdlet and the return type of both expressions is an array. If however, we do the same with only one call to the cmdlet with the script block example we get the output type from Register-ObjectEvent
:
$watcher1 = [System.IO.FileSystemWatcher]::new($pwd.Path)
$watcher2 = [System.IO.FileSystemWatcher]::new($pwd.Path)
$handler1 = . {
Register-ObjectEvent $watcher1 -EventName Changed -Action { Write-Host 'hello '}
}
$handler2 = @(
Register-ObjectEvent $watcher2 -EventName Changed -Action { Write-Host 'hello '}
)
$handler1.GetType() # => PSEventJob
$handler2.GetType() # => object[]