Home > Enterprise >  Why does my PowerShell function return Object[] instead of string[]?
Why does my PowerShell function return Object[] instead of string[]?

Time:06-29

I wrote the following function to split a string into an array of strings. There are circumstances when the input is $null, in which case the function should return $null, or when the input already is a string array, in which case the input should be returned as-is.

function Split-Tests($tests)
{
    if ($tests -eq $null)
    {
        return $tests
    }
    if (($tests.GetType() -eq [string[]]) -and $tests.Count -ne 1)
    {
        return $tests
    }
    return ([string]$tests).Split(",")
}

The function should return either $null, or a string array. However, when I call this function like Split-Tests "1,2,3", the returned value has type object[] even though the string.Split function returns string[].

I tried an explicit cast to string[] (return [string[]](([string]$tests).Split(","))) instead, and I tried the [OutputType([string[]])] attribute, but the return type remained at object[].

As a final resort, I cast the result of the function invocation to [string[]]. That works, but I would rather define the return type within the function that outside it. Can you help me?

Edit: I found this answer indicating that I could add a comma between "return" and the return value. Unfortunately, in my case it didn't help. Not even "Write-Output" mentioned in this reply made a change.

Edit again: The comma trick did it, I must've done something wrong in my first attempt.

CodePudding user response:

This is the normal behaviour. Unlike other programming languages, PowerShell unrolls arrays and outputs them element-by-element to the pipeline, as a stream. Even the return statement in PowerShell doesn't actually return the given object as-is, but outputs to the pipeline as well.

I. e.

return ([string]$tests).Split(",")

is just a shortcut for:

([string]$tests).Split(",")   # Output to the pipeline
return                        # Return from the function

When the output gets captured into a variable, PowerShell just sees the individual elements as passed to the pipeline. It doesn't know about the original array type. As the values from the pipeline could be of different types, it can only create a generic object[] array, which accepts any element type.

Function Fun { return 1,2,3,'a','b','c' }
$x = Fun  # Now x contains 3 ints and 3 strings.

To force output of a string[] array, you can use the unary form of the comma-operator in front of the array to prevent enumeration:

function Split-Tests( $tests)
{
    if ($tests -eq $null)
    {
        return $tests
    }
    if (($tests.GetType() -eq [string[]]) -and $tests.Count -ne 1)
    {
        return ,$tests
    }
    ,([string]$tests).Split(",")  # No return statement needed here
}

$a = Split-Tests "1,2,3"
$a.GetType().Name   # Outputs "String[]"
  • Related