The following is not an actual question but a cautionary tale about some unexpected PowerShell syntax. The only real question is "Is this behaviour well known to many or only by a few PowerShell developers (i.e. those working ON PowerShell not just WITH PowerShell)?" Note: the examples are only to demonstrate the effect and do not represent meaningful code (no need to ask what the purpose is).
While playing with a PowerShell (5.1.18362.145) switch
statement, I received the following error,
PS > $xx = gi somefile
PS > switch ($xx.directory) {
>> $xx.directory{6}
>> }
At line:2 char:17
+ $xx.directory{6}
+ ~
Missing statement block in switch statement clause.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingSwitchStatementClause
Given previous research on switch
, I expected both the $xx.directory
expressions to be evaluated and converted to (matching) strings. Clearly {6}
would be expected to be the statement clause. Maybe there is some weird parsing happening. Try separating the expression from the statement,
PS > switch ($xx.directory) {
$xx.directory {6}
}
6
PS >
OK, so what happens if we try both,
PS > switch ($xx.directory) {
>> $xx.directory{5} {6}
>> }
Method invocation failed because [System.IO.FileInfo] does not contain a method named 'directory'.
At line:2 char:1
+ $xx.directory{5} {6}
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
What the??? I know braces kinda look like parentheses but what is happening here? Let's try it with an actual method,
PS > 'fred'.substring{1}
Cannot find an overload for "substring" and the argument count: "1".
At line:1 char:1
+ 'fred'.substring{1}
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
but String.Substring
does have an overload with one argument, though it is supposed to be an int
. What is this trying to pass? (Hint: what does it look like?) Let's find out,
PS > Add-Type @'
>> public class huh {
>> public void passing(object o)
>> {
>> System.Console.WriteLine(o.GetType().ToString());
>> }
>> }
>> '@
PS > $whatsit=New-Object huh
PS > $whatsit.passing{1}
System.Management.Automation.ScriptBlock
PS >
Who'da thunk it?
About the only other question would be, "Anybody know where this is described in the documentation (assuming it is still happening in 7.2+)?" (Seriously, I'd like to know if it is.)