Sunday, July 4, 2021

PowerShell: Passing Values by Reference (the ref Keyword)

In PowerShell parameters passed to functions and class method are by value meaning the value of the underlying reference cannot be change when the function or method is invoked. There are functions and methods that change the underlying reference using the C# ref or out keyword. .NET's TryParse methods, for example, use out parameters:

public static bool TryParse (string? s, out int result);
public static bool TryParse (string? s, out double result);
public static bool TryParse (string? s, out DateTime result);

PowerShell's ref keyword can be used pass a value to TryParse's result parameter which is decorated by out as is shown in boldface below:

[string] $candidate = 'abc'
[Nullable[int]] $result = $null
[bool] $isValid = [int]::TryParse($candidate, [ref] $result)

Write-Host "Value: $result, Is valid: $isValid, Is null: $($null -eq $result)"

$candidate = '123'
$isValid = [int]::TryParse($candidate, [ref] $result)
Write-Host "Value: $result, Is valid: $isValid, Is null: $($null -eq $result)"

PowerShell's ref keyword works for both the C# ref and out parameters.

The code sample above worked when TryParse was invoked for the int data type. Attempting the same code for the DateTime type is as follows and this case actually fails:

[string] $candidate = 'abc'
[Nullable[DateTime]] $result = $null
[bool] $isValid = [DateTime]::TryParse($candidate, [ref] $result)

Write-Host "Value: $result, Is valid: $isValid, Is null: $($null -eq $result)"

The output from invoking the code above is as follows:


As it turns out, in order for [DateTime]::TryParse to work with invalid parse strings, the value passed to the second parameter must be assigned to valid value of type DateTime as is shown below were $result is assigned the value of Get-Date as is shown in boldface:

[string] $candidate = 'abc'
[Nullable[DateTime]] $result = Get-Date
[bool] $isValid = [DateTime]::TryParse($candidate, [ref] $result)

if (!($isValid)) {
    $result = $null # $result was not set by TryParse
}

Write-Host "Value: $result, Is valid: $isValid, Is null: $($null -eq $result)"
$candidate = '12/25/2021 08:09:11'
$result = Get-Date
$isValid = [DateTime]::TryParse($candidate, [ref] $result)

if (!($isValid)) {
    $result = $null # $result was not set by TryParse
}

Write-Host "Value: $result, Is valid: $isValid, Is null: $($null -eq $result)"

The above code executes without an error.

No comments :

Post a Comment