Monday, January 18, 2010

Reference Variables

If you want to change a value inside a function, you have to use reference variables. They do not work the same way as they do in C, C# or VbScript.

This is a simple example -

function a([ref]$v) {
"a1 v=$($v.value)"
$v.value++
"a2 v=$($v.value)"
}

$x=0
"begin x=$x"
a ([ref]$x)
"end x=$x"







Note that must use [ref] when declaring the argument and also when calling. Note also that you must use ([ref]$x) in the call. Finally, you can see that [ref] actually converts the variable into a PSReference object and that you must use .Value to set/get the value.



But what if you want to transfer the reference variable across multiple function calls? Well, the logical approach is this -




function b([ref]$v) {
"b1 v=$($v.value)"
$v.value++
"b2 v=$($v.value)"
}

function a([ref]$v) {
"a1 v=$($v.value)"
$v.value+=10
b ([ref]$v)
"a2 v=$($v.value)"
}

$x=0
"begin x=$x"
a ([ref]$x)
"end x=$x"







The pattern is simply repeated. Just like you would in other languages. But THIS WILL NOT WORK. As the first call creates a PSReference object, using ([ref]$v) creates another level of redirection and things will fail. The correct solution is -




function b([ref]$v) {
"b1 v=$($v.value)"
$v.value++
"b2 v=$($v.value)"
}

function a([ref]$v) {
"a1 v=$($v.value)"
$v.value+=10
b $v
"a2 v=$($v.value)"
}

$x=0
"begin x=$x"
a ([ref]$x)
"end x=$x"





Note that in the second call, $v – a PSReference object – is simply transferred.



Bottom line: Avoid [ref] when you can. Return values or use scoped variables when possible. Remember that it is very easy to return multiple values from a function and assign them to different variables -




function c{
"Per"
"Denmark"
44
}
$Name,$Country,$ShoeSize=c



No comments: