Related: #12915
By design, class
definitions do not support the automatic $args
variable for reporting unbound arguments.
However, a reference to $args
in a method body is currently:
This contrasts with references to variables with non-reserved variable names that haven't been initialized, which - sensibly - cause a parse-time error.
class Foo { [object] Bar() { return $Args } }; [Foo]::new().Bar().GetType().Name
A parse-time "Variable is not assigned in the method." error.
Object[]
That is, the class definition unexpectedly succeeds and calling the method yields an empty [object[]]
array.
PowerShell Core 6.2.0-rc.1
Windows PowerShell v5.1
This is probably because all reserved name variables exist at all times. Start a new session and dir variable:
and $args will be listed as {}
. Thus, it is already assigned a value, and no error occurs.
Note that classes generally don't see variables outside of it, so $args
is receiving - unwanted - special treatment here:
E.g., the following attempt to $PSHOME
- also present in pristine sessions - does _not_ work:
PS> class Foo { [object] Bar() { return $PSHOME } }; [Foo]::new().Bar() # BREAKS
Variable is not assigned in the method.
...
Conversely, trying to use $args
as a _parameter variable_ is quietly _accepted_, but doesn't work:
PS> class Foo { [object] Bar([array] $args) { return $args.Count } }; [Foo]::new().Bar(@(1, 2))
0 # !! Arguments were quietly ignored.
There is a semantic check step and we could add new check there.
My guess for the reasoning is because this is valid:
class Test {
static [void] Do() {
& { $args } 1 2 3
}
}
It's sort of hard to tell statically if $args
is valid there. Well, I guess it could only throw a parse exception if $args
is not inside a nested script block, but that's potentially a lot of extra logic going into the semantic check.
It's especially difficult for the other, similar variables which would have these requirements not to throw:
$ForEach
- A parent foreach
statement$switch
- A parent switch
statement$matches
- Any sequence point before the variable access that used the -match
operator$PSCmdlet
- In a nested scriptblock decorated with CmdletBinding
or with a parameter decorated with Parameter
(I think some other triggers as well)As much as I'm all for strict checks in classes, I'm not sure it's worth it in this case.
Makes sense, @SeeminglyScience, thanks - I'm closing this issue.
Most helpful comment
There is a semantic check step and we could add new check there.