3

I am trying to create a function that creates a custom object but have encountered unusual behavior. If you run the below code, you'll find this output

function Test-CustomObject {
    function Create-CustomObject {

        $objProps = @{ 
            'property1' = 'Hello from property 1';
            'property2' = 'Hello from property 2';
        }

        $obj = New-Object -TypeName PSCustomObject -Prop $objProps

        $obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 1' } -Name Method1 -PassThru
        $obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 2' } -Name Method2 -PassThru

        write-host "in function: $obj"
        write-host "in function type: $($obj.GetType())"

        return $obj
    }

    $newObj = Create-CustomObject
    write-host "after function: $newObj"
    write-host "after function type: $($newObj.GetType())"
}

Test-CustomObject

Program Output:

in function: @{property1=Hello from property 1; property2=Hello from property 2}
in function type: System.Management.Automation.PSCustomObject
after function:
after function type: System.Object[]

Does anyone know why the returned object is System.Object[] instead of PSCustomObject?

1
  • 1
    Why do you have a function inside of a function? Commented Apr 22, 2014 at 16:33

2 Answers 2

6

PowerShell returns everything that is not assigned to variable from function and not only statement after return keyword.

In your code it will also add result of this calls:

$obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 1' } -Name Method1 -PassThru
$obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 2' } -Name Method2 -PassThru

to function return.

To avoid this you can replace this lines with code (just adding [void] cast of call result):

[void]($obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 1' } -Name Method1 -PassThru)
[void]($obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 2' } -Name Method2 -PassThru)

after that it will work as expected.

Sign up to request clarification or add additional context in comments.

1 Comment

Oh god no. That's... terrible.
0

The updated answer to Nick's answer to this question is to assign the misbehaving commands to a variable. Special variable $null tends to fill this spot perfectly.

$null = $obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 1' } -Name Method1 -PassThru
$null = $obj | Add-Member -MemberType ScriptMethod -Value { return 'Hello from method 2' } -Name Method2 -PassThru

And then your function can Return what you tell it to.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.