Prevent variable from breaking out of Function scope

Hi
I’m now to this forum (:

I encountered the following behavior:
If you pass a variable to a function and change it inside it, it will not change the variable at the parent scope as expected (without overriding the scope with $global: or something like this).
But if you do the same with complex objects the function will override the variable on the parent scope unexpectedly.

  1. Why is that happening?
  2. How to prevent it?

Example

$VarOut = @{'A' = 'Out'}
'Start: ' + $VarOut['A'] #Will output 'Out'

function Get-Something
{
    [CmdletBinding()]
    param
    (
        $VarIn
    )
    $VarIn['A'] = 'In'
    'In function: ' + $VarIn['A'] #Will output 'In'
}
Get-Something -VarIn $VarOut

'End: ' + $VarOut['A'] #Will output 'In' and not 'Out'

Thank you

I think the problem you’re having is due to the type of value you’re passing in to the function, which is a hashtable. This is a reference type, so when you re-assign the value of the ‘A’ key, then it does it by reference to the original which is saved as variable $VarOut. There’s a decent explanation of the difference in reference and value types here:

You can see the difference if you change your script to only pass string values:

$VarOut = 'Out'
'Start: ' + $VarOut #Will output 'Out'

function Get-Something
{
    [CmdletBinding()]
    param
    (
        $VarIn
    )
    $VarIn= 'In'
    'In function: ' + $VarIn #Will output 'In'
}
Get-Something -VarIn $VarOut

'End: ' + $VarOut #Will output 'Out'

Hi

I fund the the solution, I just needed to clone it before editing

$VarOut = 'Out'
'Start: ' + $VarOut #Will output 'Out'

function Get-Something
{
    [CmdletBinding()]
    param
    (
        $VarIn
    )
    $VarIn = $VarIn.Clone() #Fix
    $VarIn= 'In'
    'In function: ' + $VarIn #Will output 'In'
}
Get-Something -VarIn $VarOut

'End: ' + $VarOut #Will output 'Out'

Thank you
“Reference types” this was the term I was looking for