Given:
PowerShell 5.1
I'm having a little trouble understanding hashtable and splatting. When splatting are use using a hash table to do that or is it something completely different?
I have the following code:
$hashtable1 = @{}
$hashtable1.add('PROD',@{ FirstName = 'John'; LastName = 'Smith'})
function Main() {
$sel = $hashtable1['PROD']
Function1 $sel
Function2 @sel
}
function Function1([hashtable] $x) {
"Value: $($x.LastName)"
$x.FirstName
}
function Function2([string] $firstName) {
"Value: $($firstName)"
}
Main
CodePudding user response:
Splatting and hashtables are related concepts in PowerShell, but they are not the same thing.
A hashtable is a data structure in PowerShell that allows you to store key-value pairs. You can think of it like a dictionary or an associative array in other programming languages. You can create a hashtable using the @{} notation and then add key-value pairs using the = operator, like so:
$hashtable = @{
"Key1" = "Value1"
"Key2" = "Value2"
}
Splatting, on the other hand, is a technique that allows you to pass a collection of parameter values to a command or function using the @ symbol. When you use the @ symbol in front of a variable that contains a hashtable, PowerShell will automatically expand the hashtable into its individual key-value pairs and pass them as separate arguments to the command or function.
For example, you could use splatting to call a function and pass the values from a hashtable as arguments:
function MyFunction([string]$Name, [int]$Age) {
Write-Host "Name: $Name"
Write-Host "Age: $Age"
}
$parameters = @{
"Name" = "John"
"Age" = 30
}
MyFunction @parameters
This will call the MyFunction function, passing the values "John" and 30 as the Name and Age arguments, respectively.
CodePudding user response:
@postanote has some very good links about hashtables and splatting and are good reads. Taking your examples, you have two different functions. One to handle hashtables as a parameter, and the second one that can only handle a single string parameter. The hashtable cannot be used to pass parameters to the second function, e.g.:
PS C:\> Function2 $sel
Value: System.Collections.Hashtable
Conceptually, the real difference between using hashtables and splatting is not about how you are using them to pass information and parameters to functions, but how the functions and their parameters receive the information.
Yes, certain functions can have hashtables and arrays as parameters, but, typically in 98% of the cases, functions don't use hashtables as a named parameter to get its values.
For ex. Copy-Item
doesn't use hash tables as a parameter. If it did, would you want to do this every time you want to copy anything:
$hashtable = @{
Path = "C:\Temp\myfile.txt",
Destination = "C:\New Folder\"
}
Copy-Item -Parameters $hashtable
No, instead, you want the parameters as strings, so you can make it a much easier one liner:
Copy-Item -Path "C:\Temp\myfile.txt" -Destination "C:\New Folder\"
It makes more sense to most people to deal with individual strings
as opposed to a generic, large, hashtable "config" to pass. Also, by separating the parameters as separate strings, integers, floats, chars, etc. it is also easier to do validation, default values, mandatory/not mandatory parameters, etc.
Now despite saying all that, there is a situation where you have certain functions with lots of parameters (e.g. sending an email message), or you want to do something multiple times (e.g. copying/moving lots of files from a CSV file). In that case, using a hashtable, and/or arrays, and/or arrays of hashtables, would be useful.
This is where splating comes in. It takes a hashtable and instead of treating it like you are passing a single value (i.e. why Function2 $sel
returns System.Collections.Hashtable
), the @
signt tells PowerShell that it is a collection of values, and to use the collection to try and match to the parameters of the function. That's why passing the hashtable to Function2
doesn't work, but splatting works e.g.:
PS C:\> Function2 @sel
Value: John
In this case, it takes the hashtable $sel
and by using splatting @sel
PowerShell now knows to not pass the hashtable as-is, but to open up the collection and to matche the $sel.FirstName
to the -Firstname
parameter.