Passing objects by reference

Public support forum for peer to peer support with related to the Visual Objects and Vulcan.NET products
Post Reply
User avatar
OhioJoe
Posts: 131
Joined: Wed Nov 22, 2017 12:51 pm
Location: United States

Passing objects by reference

Post by OhioJoe »

Another of my dumb questions:
I've always been under the impression that objects are passed by reference. Apparently not so.

Code: Select all

CLASS JoeClass INHERIT Something
HIDDEN JoeFile as XUseFile  // inherits from DBServer

METHOD JoeMethod CLASS JoeClass
  SELF:JoeFile := XUseFile( "JOE.DBF" .. )
  WHILE !SELF:JoeFile:Eof
  	? XGetTheName( SELF:JoeFile )
  	SELF:JoeFile:Skip(1)
  ENDDO
  RETURN NIL
  
FUNCTION XGetTheName( SomeFile AS XUseFile ) AS STRING STRICT
	RETURN SomeFile:FIELDGET(#NAME)
Apparently in the example above, the SELF:JoeFile object is copied when passed to XGetTheName() rather than passed by reference as I always assumed was the case. Variants of this occur hundreds of times in our main application so I'm thinking there might be a performance advantage to making the appropriate changes. First a couple of questions:

1. Is it in fact true: the object above is NOT passed by reference ?
2. And if so, how can I change the syntax so that it works in both VO and X# ?

Thanks in advance for your assistance.
Joe Curran
Ohio USA
ic2
Posts: 1862
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Passing objects by reference

Post by ic2 »

Hello Joe,

What happens here is that you open another instantiation of that dbServer. If you debug your application in VO and have a breakpoint somewhere, then click on the envelope in the upper left corner and select dbWork areas, you will see something like this
No ALIAS
1023 JOE.DBF
1024 JOE_1.DBF

and more like that with more instantiations.

It also means that you should close your object on finalizing/closing the window or method where you assigned each DBServer object.

Opening a DBF will come with a speed penalty. However, if you would open your DBF once, using something like a GLOBAL JoeFile object (or comparable), you must realize that doing something in 1 method, like a skip, moves the recordpointer in the global object with possible unwanted effects on the other places where you use JoeFile where you probably do not expect changes caused by other pieces of code.

So you may not need/want to change it everywhere but some rather "static" databases could be opened once & centrally, like lookup tables with data like countries, languages etc.

It would/could work the same in VO & X# for what you write as example.

Dick
User avatar
robert
Posts: 4555
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Passing objects by reference

Post by robert »

Joe,

In the code

Code: Select all

? XGetTheName( SELF:JoeFile )
You are passing the HIDDEN field JoeFile to the function.
The parameter is declared as

Code: Select all

AS JoeFile
That means that the original value inside SELF:JoeFile is NOT changed when you create a new object of type inside XGetTheName.

However, since the XUseFile is a class, this is a Reference type. That means that SELF:JoeFile contains a reference to the object that is in the Heap of your program.
In the call to XGetTheName you are creating a copy of the reference. That points to the same memory location, like in the image below:
Reftypes.png
Reftypes.png (7.71 KiB) Viewed 549 times
The same happens in VO and in X#. You are copying the reference, but both copies point to the same object in memory.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
Chris
Posts: 4961
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Passing objects by reference

Post by Chris »

I think there's a bit of confusion between "passed parameter by reference" and "passing a reference of the object", which are different things.
When you use this:

Code: Select all

oMyObject := MyObject{}
SomeFunc(oMyObject)
? oParam:Something // prints 1

FUNCTION SomeFunc(oParam AS MyObject) AS VOID
oParam:Something := 1

CLASS MyObject
EXPORT Something := 0 AS INT
then a reference to the object is passed to the function (you "pass a reference to the object"), and when you change something to this object properties, it is reflected to the original variable passed to it.

But when you do this:

Code: Select all

oMyObject := MyObject{}
oParam:Something := 123
SomeFunc(REF oMyObject) // or "@oMyObject"
? oParam:Something // prints 0 this time, as it's a new object

FUNCTION SomeFunc(oParam REF MyObject) AS VOID
oParam := MyObject{} // create and pass back a completely new object
now you are "passing the parameter by reference". When you do that, then you can completely change the param and assign to it a completely new object, and this new object will be passed back to the code that calls the function.

.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Post Reply