Prevent variable from breaking out of Function scope

This topic contains 3 replies, has 2 voices, and was last updated by Profile photo of Ili Metuki Ili Metuki 5 months, 2 weeks ago.

  • Author
    Posts
  • #59380
    Profile photo of Ili Metuki
    Ili Metuki
    Participant

    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

  • #59386
    Profile photo of Matt McNabb
    Matt McNabb
    Participant

    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'
    
    • #59392
      Profile photo of Ili Metuki
      Ili Metuki
      Participant

      Thank you
      "Reference types" this was the term I was looking for

  • #59388
    Profile photo of Ili Metuki
    Ili Metuki
    Participant

    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'
    

You must be logged in to reply to this topic.