2

I had a lot of trouble today, until I've figured out, that [ref] parameters of functions with type attribute are limited to positional parameters.

Examples:

function GetMessage
{
    Param ( [ref][string]$message )

    if ($message) { $message.Value = 'Hello' }
}

$message = 'ERROR'
GetMessage -message ([ref]$message)
$message

This is not working, only because of variable name -message.

Change it to:

GetMessage ([ref]$message)

and it works.

But this way, you can only have one optional typed ref parameter, the last one.

As an alternative, you could remove the type attribute:

Param ( [ref]$message )

Then the named parameter would work again:

GetMessage -message ([ref]$message)

Question: Why it should be an issue to limit named ref parameters to a type ? I guess it's a bug.

3
  • Why do you need the type when you're working with a reference? Have validation in your function for $message.value.gettype() and remove [string] from the parameter. In this case, it works either way. Also: what is your use-case for ref? I've yet to see a decent one in powershell Commented Jun 1, 2018 at 13:21
  • Of course it's for getting different values from a function. How would you do it in PS ? Returning a hashtable ? I come from C#, you know. Commented Jun 1, 2018 at 16:44
  • What's your use-case? What are you trying to accomplish? If you provide that, there are probably better directions to go. Commented Jun 1, 2018 at 16:56

1 Answer 1

2

I think it is working as designed, just not like other languages. When you define the parameters:

Param ([ref][string]$message)

PowerShell isn't seeing this as a '$message must be a pointer to a string', but is first casting $message to a string, then trying to bind it as a pointer, which it isn't by that stage. Where the casting makes sense, it works fine:

function GetMessage
{
    Param ( [DateTime][String]$message )

    if ($message) { $message.GetType() }
}

$message = [DateTime]::Now
GetMessage -message ([DateTime]$message)

Swapping [DateTime] and [String] around in the above still works ok, and you see the type you expect (i.e. whichever is leftmost in the definition).

You can get insight into what PowerShell is doing by using the Trace-Command cmdlet, like this:

Trace-Command -Name metadata,parameterbinding,cmdlet -Expression {
    $message = [DateTime]::Now
    GetMessage -message ([string]$message)
} -PSHost
Sign up to request clarification or add additional context in comments.

1 Comment

ok, but the question was, why is the casting to a string first, preventing the usage as a named ref parameter? As a positional parameter is works as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.