Home Dashboard Directory Help
Search

-f format operator bug when right-side value is an array variable by Larry Weiss


Status: 

Closed
 as Fixed Help for as Fixed


14
0
Sign in
to vote
Type: Bug
ID: 518276
Opened: 12/4/2009 1:37:53 PM
Access Restriction: Public
2
Workaround(s)
view
8
User(s) can reproduce this bug

Description

Referencing the .length property of an array used as right side values of the -f format operator impacts negatively thereafter on the runtime results of that operator

Consider this transcript

<# beginning of transcript #>
PS C:> $b = 7,8,9
PS C:> '[{0}][{1}][{2}]' -f $b
[7][8][9]
PS C:> '[{0}]' -f $b.length
[3]
PS C:> '[{0}][{1}][{2}]' -f $b
Error formatting a string: Index (zero based) must be greater than or equal to
zero and less than the size of the argument list..
At line:1 char:21
+ '[{0}][{1}][{2}]' -f <<<< $b
    + CategoryInfo         : InvalidOperation: (7 8 9:PSObject) [], RuntimeEx
ception
    + FullyQualifiedErrorId : FormatError
<# end of transcript #>

Notice the unexpected error at the second instance of
'[{0}][{1}][{2}]' -f $b
Details
Sign in to post a comment.
Posted by yecril on 1/27/2014 at 12:59 AM
My test:

[BYTE[]] $L = 0
IF (('{0}' -F $L) -NE 'System.Byte[]') { THROW }
[VOID] $L.LENGTH
IF (('{0}' -F $L) -NE '0') { THROW }

This is actually sort-of specified so perhaps it is by design:

•    If the parameter type is not a collection, but the argument is some sort of collection, no conversion is attempted unless the parameter type is object or PsObject. (The main point of this restriction is to disallow converting a collection to a string parameter.) Otherwise, the usual conversions are attempted.

Posted by Larry Weiss on 12/9/2009 at 5:52 PM
According to my reading of my copy of Bruce Payette's book
"PowerShell in Action"

"{0}" -f $a
should be equivalent to
[string]::Format('{0}',$a)

Is this actually true in all cases?
Posted by Richard Berg on 12/9/2009 at 1:42 PM
And also http://groups.google.ca/group/microsoft.public.windows.powershell/browse_thread/thread/a90e7c1c04fa4837
Posted by Richard Berg on 12/9/2009 at 1:40 PM
@Powershell folks - see the full discussion here: http://stackoverflow.com/questions/1872146/powershell-how-exactly-does-the-rhs-of-the-f-operator-work/1875090#1875090
Posted by Joel 'Jaykul' Bennett on 12/8/2009 at 2:50 PM
I have to say, I think the BUG is the original behavior where $b is being splatted even though the splat operator wasn't used. Consider:

> $a = 1,2,3

# THIS is what we expect when we put an array in a string in PowerShell
> "$a"    
1 2 3

# THIS is clearly a bug
> "{0}" -f $a
1

# So is this:
> "{0},{1}" -f $a,"one"
System.Object[],one

# So is this:
> "{0},{1}" -f @($a),"one"
System.Object[],one

# But not this:
> "{0},{1}" -f ([PSObject]$a),"one"
1 2 3,one
Sign in to post a workaround.
Posted by Joel 'Jaykul' Bennett on 12/8/2009 at 3:08 PM
OK, my original workaround isn't actually correct -- it restores the BUGGY behavior all of the time, instead of the CORRECT behavior (which is for an array to be treated as a single item passed to string formatting, and formatted using the $OFS separator).

The correct workaround would be to cast the array to [PSObject] when you create it:

[PSObject]$a = 1,2,3

Or, to create a strongly-typed integer array:

[PSObject][Int[]]$a = 1,2,3

That way, you get the same results from:

> "$a"
1 2 3

>"{0}" -f $a
1 2 3

And it doesn't change if you touch the properties, and it's still typesafe, and respects the setting of $OFS


Posted by Joel 'Jaykul' Bennett on 12/8/2009 at 2:22 PM
As a workaround: ALWAYS wrap arrays with an @() when passing to formatting @($b)

[335]: $a = 1,2,3
[336]: "{0}" -f @($a)
1
[337]: $a.Length
3
[338]: "{0}" -f @($a)
1