You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A ValueFromRemainingArguments parameter by default invariably receives a [List[object]] collection rather than a scalar / PowerShell array ([object[]]), as appropriate #4625
Declaring a (at most 1) parameter with attribute ValueFromRemainingArguments allows you to collect any remaining arguments - those not bound to other parameters - in a single parameter.
Given that there may be 1 or more remaining arguments, that would usually imply:
bind a scalar to the parameter if there's only one remaining argument
bind a regular PowerShell array ([object[]]), if there are multiple remaining arguments.
By contrast, a [List[object]] instance is currently bound, irrespective of whether 1 or more remaining arguments are bound.
Steps to reproduce
Create script t.ps1 in the current dir. with the following content:
PowerShell Core v6.0.0-beta.5 on macOS 10.12.6
PowerShell Core v6.0.0-beta.5 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.0-beta.5 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.483 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
changed the title [-]ValueFromRemainingArguments parameters by default invariably receive a [List[object]] collection rather than a scalar / PowerShell array ([object[]]), as appropriate[/-][+]A ValueFromRemainingArguments parameter by default invariably receives a [List[object]] collection rather than a scalar / PowerShell array ([object[]]), as appropriate[/+]on Aug 20, 2017
Parameters that use ValueFromRemainingArguments usually specify an array type, but if the type is omitted, isn't it more useful to pass a collection? The command probably expects a collection anyway.
It is useful in the same way that cmdlets (e.g., Get-ChildItem) return collections - but, by virtue of going through the pipeline, they output:
either a [System.Object[]] array
or, if the collection happens to contain a single item only, a scalar.
I get the backward compatibility concern, but what good reason is there for ValueFromRemainingArguments parameters and common parameters -OutVariable, -ErrorVariable, -WarningVariable, and -InformationVariable do deviate from these fundamental behaviors?
Given that we're already willing to fix the issue for -OutVariable, even though it is a breaking change - #3154 - this strikes me as a great opportunity to fix the issue fundamentally, given that the other cases are probably less common than -OutVariable.
Also, while technically a breaking change, I wouldn't expect it to be a problem in practice, given that, if a scalar is returned in the future for single-item collections, things should continue to work, thanks to being able to use .Count and indexing on scalars too.
I suppose there could be code out there that relies on the specific collection types returned ([List[object]] for ValueFromRemainingArguments, and [System.Collections.ArrayList] for the common parameters), but that strikes me as unlikely.
Comparing this issue to -OutVariable is interesting. I think the primary use case for OutVariable is the scalar case, which is why we were open to a change.
ValueFromRemainingArguments has the opposite expectation - the primary case being a collection.
Revisiting this I agree that it makes more sense to always create a collection for a (non-type-constrained) ValueFromRemainingArguments parameter variable, given that the point of such a parameter is to expect a variable number of arguments, and that the script/function author has to be prepared to handle multiple arguments.
This reduces the issue at hand to suggesting use of object[] instead of List`1 - but, unlike in the #3154 case, this technical difference is unlikely to matter, so I'm closing this.
If the parameter is untyped or [object]/[psobject]-typed:
If a single scalar argument is passed, $P1 is a new List<T> instance.
If multiple arguments are passed, $P1 is a new List<T> instance.
If a single collection argument is passed, $P1 is a reference to that collection.
If the parameter is typed as anything other than [object]/[psobject], $P1 is of whatever that type is.
In older versions, there was no asymmetry in scenario 1. The result was invariably a new List<T> instance (for 1.3, a single-element list containing the collection).
Activity
[-]ValueFromRemainingArguments parameters by default invariably receive a [List[object]] collection rather than a scalar / PowerShell array ([object[]]), as appropriate[/-][+]A ValueFromRemainingArguments parameter by default invariably receives a [List[object]] collection rather than a scalar / PowerShell array ([object[]]), as appropriate[/+]lzybkr commentedon Aug 21, 2017
Parameters that use
ValueFromRemainingArgumentsusually specify an array type, but if the type is omitted, isn't it more useful to pass a collection? The command probably expects a collection anyway.This would also be a breaking change.
mklement0 commentedon Aug 21, 2017
It is useful in the same way that cmdlets (e.g.,
Get-ChildItem) return collections - but, by virtue of going through the pipeline, they output:[System.Object[]]arrayI get the backward compatibility concern, but what good reason is there for
ValueFromRemainingArgumentsparameters and common parameters-OutVariable,-ErrorVariable,-WarningVariable, and-InformationVariabledo deviate from these fundamental behaviors?mklement0 commentedon Aug 21, 2017
P.S.:
Given that we're already willing to fix the issue for
-OutVariable, even though it is a breaking change - #3154 - this strikes me as a great opportunity to fix the issue fundamentally, given that the other cases are probably less common than-OutVariable.Also, while technically a breaking change, I wouldn't expect it to be a problem in practice, given that, if a scalar is returned in the future for single-item collections, things should continue to work, thanks to being able to use
.Countand indexing on scalars too.I suppose there could be code out there that relies on the specific collection types returned (
[List[object]]forValueFromRemainingArguments, and[System.Collections.ArrayList]for the common parameters), but that strikes me as unlikely.lzybkr commentedon Aug 21, 2017
Comparing this issue to
-OutVariableis interesting. I think the primary use case forOutVariableis the scalar case, which is why we were open to a change.ValueFromRemainingArgumentshas the opposite expectation - the primary case being a collection.mklement0 commentedon Aug 21, 2017
Absolutely - but the larger point is that all these features should be familiar PS citizens, which means:
use
[object[]]arrays rather than some collection type not otherwise used publicly in PowerShell.output a scalar if a collection happens to contain 1 item only.
mklement0 commentedon Aug 22, 2017
Just ran into another case where the above expectations are confounded: #4642
mklement0 commentedon Nov 16, 2020
Revisiting this I agree that it makes more sense to always create a collection for a (non-type-constrained)
ValueFromRemainingArgumentsparameter variable, given that the point of such a parameter is to expect a variable number of arguments, and that the script/function author has to be prepared to handle multiple arguments.This reduces the issue at hand to suggesting use of
object[]instead ofList`1- but, unlike in the #3154 case, this technical difference is unlikely to matter, so I'm closing this.surfingoldelephant commentedon Jan 28, 2025
It's worth noting there's asymmetry between positional input passed as:
This affects untyped or
[object]/[psobject]-typed parameters.For completeness, when the parameter is typed:
Summary:
[object]/[psobject]-typed:$P1is a newList<T>instance.$P1is a newList<T>instance.$P1is a reference to that collection.[object]/[psobject],$P1is of whatever that type is.In older versions, there was no asymmetry in scenario 1. The result was invariably a new
List<T>instance (for 1.3, a single-element list containing the collection).I believe this is a by-product of #2035.