Article
· Aug 1, 2016 2m read

Tips & Tricks - ByRef object passing

Today, I was reading some source code, and encountered the following method signature:

Method SendRequestSync(pRequest As %Library.Persistent, ByRef pResponse As %Library.Persistent)

And I immediately thought, why is there a ByRef?

Beforehand, I was under a (correct) assumption that objects are always passed by a reference, without exception. So, what does ByRef does here? A quick search in documentation yielded information on ByRef  for non-object variables , but it was not what I was searching for.

Turns out that you can pass a reference by reference therefore allowing reference modification in a called code. To clarify, consider this example:

Class Utils.ObjByRef [ Abstract ]
{

/// Do ##class(Utils.ObjByRef).Test()
ClassMethod Test(UseByRef As %Boolean = {$$$YES})
{
    Set Obj = {}
    Set Obj.Property = 1
    Write "At the begining ",Obj.Property,!
    Do ..RefMethod(Obj)
    Write "After Value pass ",Obj.Property,!
    Do ..RefMethod(.Obj)
    Write "After ByRef pass ",Obj.Property,!
}

ClassMethod RefMethod(ByRef Obj)
{
    Set Obj = {}
    Set Obj.Property = 500
}

}

It produces the following output:

>Do ##class(Utils.ObjByRef).Test()
At the begining 1
After Value pass 1
After ByRef pass 500

In the first case we pass object reference by value, so if the called code changes the reference,  the caller doesn't know about it. In the second case the reference is also passed by reference, so if the called code modifies the reference, the caller would get a new reference.

Do you use this feature? How?

Discussion (4)1
Log in or sign up to continue

I use ByRef a lot, but mostly to indicate that an array or object will be changed in the method. 

In fact, until now, I thought it was necessary to use ByRef in order to "continue the changes to the object back to the calling code".  However, after playing around with some code, including your example, I see that it's not necessary at all, which makes me think that it's useful as an "annotation", so that the programmer knows that the object WILL BE changed. 

Now, I feel that the real "pass by reference" is the dot in front of the variable, and the ByRef is merely an indicator that this variable could be changed when returned.

Is this true?  I'm not really sure what "passing a reference by reference" would produce. I came upon this article because I want several methods in a row to update a log file, which I sometimes add to the method signature as ByRef, and sometimes I don't, and I wanted to know why it still worked (i.e. my log file is created, and is updated in the calling method).

Here is your original example, but without the ByRef:

ClassMethod Test(UseByRef As %Boolean = {$$$YES})
{
    Set Obj = {}
    Set Obj.Property = 1
    Write "At the begining ",Obj.Property,!
    Do ..RefMethod(Obj)
    Write "After Value pass ",Obj.Property,!
    Do ..RefMethod(.Obj)  // pass by reference because I want the object to change
    Write "After ByRef pass ",Obj.Property,!
}

/// notice there's no ByRef in the method signature

ClassMethod RefMethod(Obj)
{
    Set Obj = {}
    Set Obj.Property = 500
}

USER>Do ##class(Utils.ObjByRef).Test()


At the begining 1
After Value pass 1
After ByRef pass 500

And, yes, I just found this: https://cedocs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GORIENT_class_method_variables_passing

So in conclusion, the ByRef is basically an "annotation", so that the programmer knows that an object will be changed and returned.  I use it all the time to change objects, on purpose, especially log files, and arrays that I need defined in a single source.