enigma_0z
enigma_0z

Reputation: 63

How do I force a function to return a single element array instead of the contained object?

I have a function (actually several instances of this), but there are times that it may return a list of several elements, and there are times that it may return a single element. I want the function to return an array ([System.Object[]]) every time so that (on the receiving end), I can always anticipate it being an array and index into it, even if I am just pulling the 0th element.

I've tried casting the return type multiple ways (see code below) ... including (for example) return @("asdf"), return [System.Object[]]@("asdf") and similar, but it seems that the only to get a consistent behavior is to add a second null element in the array ... which feels wrong to me. (See code below)

function fn1 {
    return @("asdf")
}

function fn2 {
    return [array]@("asdf")
}

function fn3 {
    return [System.Object[]]@("asdf")
}

function fn4 {
    # This works but with the side effect of sending a null string that is not actually necessary
    return @("asdf",$Null)
}

$v = fn1            # Same for fn2, fn3.
$v.GetType().Name   # Expected: Object[], Actual: String
$v[0]               # Expected: "asdf", Actual: "a"

$v = fn4
$v.GetType().Name   # Expected: Object[], Actual: Object[]
$v[0]               # Expected: "asdf", Actual: "asdf" 

Upvotes: 3

Views: 334

Answers (3)

user28305906
user28305906

Reputation: 1

You can create the function, call the array results and then store them in the array again using a foreach-object loop.

Function make-Array { 
param (
   $something
)
<# some code here, param is optional #>
$some_array = @(time1, item2, item3) 
<# 
make sure to call the array here, this will print out all the contents of the array.
#>
$some_array
return #leave this blank
}

This is where you can get the array stored. You need to pipe it into a Foreach-Object loop. Iterating through each obejct. To be honest, i'm sure there areother ways to iterate through theh outputs to add them to an array as well.

Make-Array $data | Foreach-object {$some_array += $_}

This will now take each deserialized output from the array in the function and then add them back again to the array, or anything else you'd like. Sicne the arrya is already global you do not need to pass it as an argument to the function nor do you need to declare it inside the funciton.

Upvotes: 0

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174505

As an alternative to wrapping in an extra array, use Write-Output -NoEnumerate:

function fn1 {
  Write-Output @('asdf') -NoEnumerate
}

or, in cmdlet-bound/advanced functions prior to version 4.0:

function fn1 {
  [CmdletBinding()]
  param()

  $PSCmdlet.WriteObject(@('asdf'), $false)
}

Upvotes: 5

Bill_Stewart
Bill_Stewart

Reputation: 24555

If I understand your question, you can use the , operator when returning the value; e.g.:

function fn1 {
  ,@("asdf")
}

The function will output a single-element array.

Upvotes: 3

Related Questions