Arguments as an array

Arguments for constructors can be passed in as an array. Each of the following may be used to create an instance of a StringBuilder object:

$params = @{
TypeName = 'System.Text.StringBuilder'
ArgumentList = 'Initial value', 50
}
$stringBuilder = New-Object @params
$stringBuilder = New-Object System.Text.StringBuilder($argumentList)

Attempting to pass in a list of arguments using the new method will produce a different result; the initial string will be filled with both values:

PS> $argumentList = 'Initial value', 50
PS> $stringBuilder = [System.Text.StringBuilder]::new($argumentList)

PS> Write-Host $stringBuilder.ToString() -ForegroundColor Green
PS> $stringBuilder

Initial value 50
Capacity MaxCapacity Length
-------- ----------- ------
16 2147483647 16

An array can be passed in using new, by adopting a slightly different approach:

PS> $stringBuilder = [System.Text.StringBuilder]::new.Invoke($argumentList)
PS> Write-Host $stringBuilder.ToString() -ForegroundColor Green
PS> $stringBuilder

Initial value
Capacity MaxCapacity Length
-------- ----------- ------
50 2147483647 13

The ability to push arguments into an array presents a complication when an argument is an array. For example, the memoryStream (System.IO.MemoryStream) class has a number of constructors; two of these expect an array of bytes, as shown in the following screenshot:

The first of these only expects an array (of bytes) as input. The following example shows an error generated when attempting to pass in the array:

PS> [Byte[]]$bytes = 97, 98, 99
PS> $memoryStream = New-Object System.IO.MemoryStream($bytes)

New-Object : Exception calling ".ctor" with "3" argument(s): "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection."
At line:2 char:17
+ $memoryStream = New-Object System.IO.MemoryStream($bytes)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

PowerShell treats each byte as an individual argument for the constructor, rather than passing all of the values into the intended constructor.

The new static method does not suffer from this problem:

[Byte[]]$bytes = 97, 98, 99 
$memoryStream = [System.IO.MemoryStream]::new($bytes) 

To work around the problem in earlier versions of PowerShell, the unary comma operator may be used as follows:

$memoryStream = New-Object System.IO.MemoryStream(,$bytes) 

Using the comma operator prevents PowerShell from expanding the array into a set of arguments. The array, held in bytes, is wrapped in another array that contains a single element. When PowerShell executes this, the wrapper is discarded, and the inner array (bytes) is passed without further expansion.

PowerShell will cast and coerce types

The preceding examples can be significantly shortened, as PowerShell will do a lot to call appropriate constructors when casting. This extended example will do the following:
  • Create an array of characters from a string
  • Create a byte array from the array of characters
  • Create a memory stream from the byte array
  • Create a binary reader from the memory stream
using namespace System.IO
[BinaryReader][MemoryStream][Byte[]][Char[]]'hello world'
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.137.164