PS for .NET devs part 2: Comparing the PowerShell language to C#
In my previous posts in this series I discussed why you should care about PowerShell and I pointed to some resources to help you get started with PowerShell. This post will describe the syntax of the PowerShell language by comparing it with the syntax of C#. Recently the PowerShell language specification was released under the community promise, so if you want to learn everything there is to know about the PowerShell language look it up.
To summarize this post: When translating a piece of C# code to
PowerShell take what you would normally write in C#, remove all
the explicit typing and add a few $
’s here and there. The comparison
is mostly presented in a tabular form showing the C# syntax in the
first column and the equivalent PowerShell syntax in the second,
followed with a description of the particular language construct in
the last column. Enjoy.
Comments
C# | PowerShell | Description |
---|---|---|
// | # | single line |
/* ... */ | <# ... #> | multi line |
/// | single line documentation comments |
Comment documentation keywords
PowerShell is also blessed with comment-based help but
because it does not have any formating keywords and does not focus on
types, a lot of the corresponding keywords have no equivalent in the
PowerShell column. PowerShell supports more keywords than
the ones listed below for the entire story please use
PowerShell’s built in help: help about_Comment_Based_Help
or the online documentation:
C# | PowerShell | Description |
---|---|---|
<c> | Set text in a code-like font | |
<code> | Set one or more lines of source code or program output | |
<example> | .EXAMPLE | Indicate an example |
<exception> | Identify the exceptions a method can throw | |
<include> | .EXTERNALHELP | Includes XML from an external file |
<list> | Create a list or table | |
<para> | Permit structure to be added to text | |
<param> | .PARAMETER | Describe a parameter for a method or constructor |
<paramref> | Identify that a word is a parameter name | |
<permission> | Document the security accessibility of a member | |
<remarks> | Describe a type | |
<returns> | .OUTPUTS | Describe the return value of a method |
<see> | .LINK | Specify a link |
<seealso> | .LINK | Generate a See Also entry |
<summary> | .SYNOPSIS | Describe a member of a type |
<value> | Describe a property | |
.NOTES | Additional information about the function or script | |
.DESCRIPTION | A detailed description of the function or script | |
.INPUTS | The inputs that can be piped to the function or script |
Literals
Literals are the same as in C# with a few minor differences:
- In PowerShell the backtick (
`
) is the escape character:PS>"Quotes need to be escaped `""
- PowerShell does not have
char
literals to create one you have to use a cast:[char]"a"
. - PowerShell multi-line strings also begin with the
@"
it however has to be followed by a new line, furthermore the end mark is a"@
which has to be put at the beginning of the line. - Array literals are created using the array operator
,
. So"Fred","Barney"
creates on array containing 2 strings. - PowerShell distinguishes single quoted
''
and double quoted""
string literals the former causes the string to be interpreted verbatim while the later is subject to string interpolation. Here’s an example:
|
|
- PowerShell supports
HashTable
literals of the form:@{ <name> = <value>; [<name> = <value> ] ... }
. Below you can see thatHashTable
literals can be split across multiple lines in which case the semicolons (;
) after the name-value pair can be omitted leaving a nice and readableHashTable
behind.
|
|
Variables
In PowerShell variable declarations don’t require explicit
typing, they do however have to be prefixed with a $
.
|
|
Being a .NET developer you’re probably wondering how you can create
objects in PowerShell. There is no new
keyword but there is a
New-Object
Cmdlet. It can for example be used like
this:
|
|
To have a little bit more brevity in the shell you don’t have to
specify the entire full name of the type. PowerShell has some
built-in type accelerators so for instance in the case of
System.DateTime
you can leave of the System
namespace part. See
this StackOverflow question for some extra
references about the subject. As you can see the New-Object
Cmdlet can also be used to create COM objects see help New-Object
for more details or look at the
online documentation.
Operators
The arithmetic and assignment operators are the same for C# and
PowerShell the differences start with the comparison operators
the familiar >
and friends are replaced with a -
followed by an
abbreviation for the comparison. This was done to keep the meaning
of >
for redirection as all system administrators now it from dos and
POSIX shells.
Apart from this table above there are a couple of extra operators that have no C# equivalent:
- Redirection operators:
>, >>, 2>, 2>&1
- Comma operator:
,
Creates an array. - Split and Join operators:
-split,-join
To divide and combine substrings1 2 3 4 5
PS>1,2,3 -join '*' 1*2*3 PS>$env:PATH -split ';' %SystemRoot%\system32\WindowsPowerShell\v1.0\ ⋮
- Call operator:
&
Run a command, script, or script block.1
PS>& 'C:\Program Files (x86)\GNU\GnuPG\sha256sum.exe' test.iso
- Dot sourcing operator:
.
Runs a script so that the variables, functions defined in the script are part of the calling scope. - Static member operator:
::
Used to call static method or retrieve static properties of a .NET Framework class.1
[Math]::Sin(([Math]::PI)/2)
- Range operator:
..
Represents the sequential integers within the given upper and lower boundary.1 2
PS>1..10 -join ',' 1,2,3,4,5,6,7,8,9,10
- Format operator:
-f
The following two pieces of code are equivalent (starting with C#):1
Math.PI.ToString("{0:0.00}")
1
"{0:0.00}" -f [Math]::PI
- Subexpression operator:
$()
Returns the result of one or more statements. Very handy in string interpolation like1 2 3
PS>"This machine has $([Environment]::ProcessorCount) cpu's" This machine has 2 cpu's
- Array subexpression operator
@()
Returns the result of one or more statements as an array.
Selection Statements
PowerShell supports the if-else
and switch
statements.
The if-else
differs only in the fact that PowerShell has a
elseif
keyword where C# uses else if
.
In PowerShell the switch
statement has more functionality
compared to C# since it supports switching on regular expressions and
wildcards when the values supplied let themselves be converted to
strings. Again use help about_Switch
(or look here).
Iteration Statements
Even though it’s not explicitly mentioned in the table above
PowerShell also supports the familiar break
and continue
keywords. See help about_break
(or here) and help about_continue
(or
here) for details. When using ForEach-Object
the
Automatic Variable $_
represents the current item, see help about_Foreach
for details.
Exception Handling
Since version 2 PowerShell supports the C#
try-catch-finally
syntax besides the earlier introduced
trap
keyword, which can be viewed as a catch
block with an
implicit try
for the surrounding scope. PowerShell also
supports throw
, the difference being that any expression
can be throw
n. The expression in the throw
syntax is optional, this reminds me a bit of the Perl
die
function.
Functions
Functions in PowerShell are quite a different beast when compared to C#. At first glance there are many similarities, both languages support positional parameters, keyword parameters and optional parameters. The extra benefit in the case of PowerShell in my opinion is, the ability to use pipeline parameters. Lets look at an example:
|
|
Here you can see the filtering of the pipeline input in a way that
reminds me of Awk, the begin
and end
syntax
specifically. The begin
and end
blocks mean exactly what you think
they mean. The process
block gets called by PowerShell for each
value received from the pipeline. Where $_
has the value of the
Current
value as in the value of the Current
property when using the IEnumerator
interface. Since
version 2 a lot of functionality was added to provide extra
functionality to functions, the so called Advanced Functions see
help about_Functions_Advanced
for details this includes stuff like
declarative parameter validation, specifying parameter sets, aliases
and a brief help message for parameters. Elaborating on the earlier
Get-SumOfSquares
example a full blown implementation could look
something like this:
|
|
After pasting this in the PowerShell console an example usage might look like the screenshot below.
Epilogue
This is my brief summary of the syntactic differences between C# and PowerShell. I hope this can help you with coming to grips with PowerShell. Next time we’ll look at how easy it is to work with XML in PowerShell and munge a large MSBuild file with a small script.
References
- PS for .NET devs part 0: PowerShell what is it and why should I care?
- Scripting with Windows PowerShell
- PS for .NET devs part 1: Getting started with PowerShell
- Powershell Language specification announcement
- About Break
- About Comment Based Help
- About Continue
- About Switch
- About Throw
- About Trap
- About Try, Catch, Finally
- The Perl Programming Language
- The Perl die Function
- MSBuild
- New-Object
- Cmdlet overview
- StackOverflow question about type accelerators
- StackOverflow
- Current property
- IEnumerator interface
- About Functions Advanced
- The Awk programming language
- GNU Awk Begin End syntax
- About Foreach
- ForEach-Object
- About Automatic Variables