Passed only a Pointer and not a Value?

I have a class called BezSeg that has various properties including node (an integer).

The following code is in the Open event of a window. That window contains a control named cnvDrawArea which is an instance of a custom control. That custom control has a property aBS which is an array of BezSeg. When this code begins, this array has no members.

  Var someBezSeg As New BezSeg
  someBezSeg.node = 5
  // … other properties also assigned values

   Self.cnvDrawArea.aBS.Add(someBezSeg)

  someBezSeg.node = 20
   // … other properties also assigned values
 
  Self.cnvDrawArea.aBS.Add(someBezSeg)

At this point, there are two members of the aBS array. They both have a node property with the value 20. Even though the line of code
Self.cnvDrawArea.aBS.Add(someBezSeg) = 5
was issued and briefly the first element of the aBS array had a node property of 5, eventually, that element ends up with the same property values as the second element (i.e. 20). Seemingly, as long as someBezSegment is in scope, the first element of the aBS array will simply track the value currently in someBezSeg.

If True Then
  Var someBezSeg As New BezSeg
  someBezSeg.node = 5
  // … other properties also assigned values

  Self.cnvDrawArea.aBS.Add(someBezSeg)
End If

If True Then
  Var someBezSeg As New BezSeg
  someBezSeg.node = 20
  // … other properties also assigned values
  
  Self.cnvDrawArea.aBS.Add(someBezSeg)
End If

This code “solves” the problem. The first element of aBS’s property node retains the value that was specifically assigned to it (5).

In this version, the variable someBezSeg goes out of scope once the code leaves the If/End If wrapping, and the first element of aBS securely holds on to its 5 value. It will not be changed by any code downstream.

I find this behavior confusing. Can someone explain it? Is there a more elegant way of addressing it than using the If/End If wrapping.

I brought someBezSeg into the code in the first place to make it easier to follow what was going on in the debugger where it is easiest to follow a local variable. The actual code, from which I have extracted this “simplified” example, is more complex.

Norman has written a lot on the Xojo Blog about by reference or by value.

https://blog.xojo.com/2018/12/12/what-kind-of-variable-are-you/
https://blog.xojo.com/2019/01/23/byref-vs-reference-types/
https://blog.xojo.com/2019/01/24/some-follow-up-regarding-byref/

1 Like

You’re storing two references to the same instance of BezSeg. Instead create a new instance each time you add to the array.

  Var someBezSeg As New BezSeg ' first instance
  someBezSeg.node = 5
  Self.cnvDrawArea.aBS.Add(someBezSeg) ' store the first instance in the array

  someBezSeg = New BezSeg '  create a second instance in the same local variable
  someBezSeg.node = 20
  Self.cnvDrawArea.aBS.Add(someBezSeg) ' store the second instance
3 Likes

Well, Andrew give you the “solution”, but you need to look a little deepper into how objects work.

In this code:

Var someBezSeg As New BezSeg

someBezSeg is NOT an object is a reference to an object.

In the line:

Self.cnvDrawArea.aBS.Add(someBezSeg)

You are creating a second REFENCE to the first instance of the object, not “moving” the object into the array.

So, in a code like this:

Var someBezSeg As New BezSeg
SomeArray.Add(someBezSeg)
Var AnotherBezSeg As BezSeg = SomeArray(0)
Var YetAnotherBezSeg As BezSeg = someBezSeg

You have FOUR references to a SINGLE instance.

1 Like

You have FOUR references to a single instance.


So as I understand what you are saying since the New word does not appear in any of the lines immediately above, I am only creating references to the single instance that was created with the line

Var someBezSeg As New BezSeg


However, if I wrote the line

Var AnotherBezSeg As New BezSeg = SomeArray(0)

What would I have done? Would I have created another instance that happens to have the same properties as the SomeArray(0)?

Sorry for all this verbiage, but I am trying to fix these notions in my brain.

NO: There are a lot of things going on there

  1. Create a whole NEW instance,
  2. Create a REFERENCE to that instance in AnotherBezSeg
  3. Remove the reference to that second instance and replace it with whatever reference was in SomeArray(0)
  4. Finally, as the second instance has no references, Xojo DESTROYS that second instance

So, you end with ONE instance and 2 references

1 Like

the use of “new” make no sense because you create and overwrite it with other value / instance or nil depending on what is in SomeArray(0)

a object / instance exists as long it is in use somewhere.
you have to care about the variable scope.

see also
https://documentation.xojo.com/api/language/is.html

1 Like