A good question on the discord server I participate in prompted a good question. It started with IS and = are just synonyms right?
It turns out that MOST times this may be true. But not always. And that little “but not always” can get you in trouble if you dont know when the difference is important.
IS is always used to determined if one instance of a class refers to the exact same instance as another reference. You might want to reread my prior post about classes, instances and objects
And in many cases, but not all, = will give you the same result as using IS.
So code like
Dim d1 As New Class2
Dim d2 As New Class2
If d1 = d2 Then
System.debuglog "d1 = d2 => true !"
Else
System.debuglog "d1 = d2 => FALSE !"
End If
If d1 Is d2 Then
System.debuglog "d1 IS d2 => true !"
Else
System.debuglog "d1 IS d2 => FAlSE !"
End If
will usually put out debug log messages that say D1 = D2 => false from both checks.
This assumes that our class, Class2, does NOT implement operator_compare. And that is the caveat here. IF a class implements operator_compare the IS and = operators may not give the same result any longer.
Operator_compare is often used to compare the contents of a class – and not the references (although it doesnt have to compare contents since you can make it do whatever you want).
If we defined our class, Class2, like
Protected Class Class2
Sub Constructor(contents as string)
myContent = contents
End Sub
Function Operator_Compare(rhs as Class1) As integer
If rhs Is Nil Then
Return -1
End If
If Self.myContent < rhs.myContent Then
Return -1
End If
If Self.myContent > rhs.myContent Then
Return 1
End If
Return 0
End Function
Private myContent As String
End Class
Now our code above will give very different results because Operator_compare is used when the line
If d1 = d2 Then
is run. In this case it will call the custom operator_compare method and that compares the contents of two objects and NOT whether or not two objects references refer to the same object. However, the line
If d1 Is d2 Then
will ALWAYS determine if the two objects references refer to the same instance.
And now you know !
Good to know. Thanks for the explanation!
My apologies if this is getting off-topic, but what about the case of comparing objects to Nil?
I’ve been avoiding using the IsNull function (unless the referenced object is already a Variant), so when checking whether a class is not instantiated yet, I’ve been using:
If d1 = Nil Then
d1 = New Class2
End If
But could I also use “d1 Is Nil” to reliably get the same result? Some quick local testing appears to say yes, but I can’t really find any documentation on this. The only hint I found was in the VB Migration page where it notes that “Is Nil” is a Xojo substitute for the VB IsNull function.
Any insight would be appreciated. Thank you Norman, this is great stuff.
you should use Is Nil as it can have the same issues IF the class has operator_compare implemented
D1 IS Nil is the right way to get the most reliable result
Hi Norman,
may I pester you with another question?
In the forum thread https://forum.xojo.com/7243-adding-event-to-containercontrol Ed Palmer posted an example https://www.dropbox.com/s/60t0enp61a6i4ae/EventPassing.xojo_binary_project?dl=1 to demonstrate how to communicate from a TextField control inside a ContainerControl to other TextField controls on the window.
He basically adds
• the KeyDown and KeyUp events to the TextField inside the ContainerControl
• the KeyDown and KeyUp events to the ContainerControl itself
• a KeyDown and KeyUp event definition to the ContainerControl
• the KeyDown and KeyUp events to the instance of the ContainerControl
In the TextField on the ContainerControl he raises the parent’s Key events:
Function KeyDown(Key As String) Handles KeyDown as Boolean
Return RaiseEvent KeyDown(Key)
End Function
Sub KeyUp(Key As String) Handles KeyUp
RaiseEvent KeyUp(Key)
End Sub
In the Key events of the instance of the ContainerControl he then implements the action:
Function KeyDown(Key As String) Handles KeyDown as Boolean
txtDown.Text = txtDown.Text + Key
End Function
Sub KeyUp(Key As String) Handles KeyUp
txtUp.Text = txtUp.Text + Key
End Sub
Now my question:
The KeyDown and KeyUp events of the ContainerControl contain no code. But if I remove them then I get an error:
This property has the same name as an event. You must resolve this conflict.
Event KeyUp(key as string)
Is that event only used when it is being added to the parent?? Surely not?
If however I add new event definitions KeyDown2 and KeyUp2 to the ContainerControl and raise those from the TextField, then it works as I would expect and I do NOT need to add them to the ContainerControl too.
So why do I need to do this for the build-in events?
TiA
Markus
The reason you have to do it this way is that a container control, by default, has its own KeyDown and KeyUp events that, if the base control does not implement them, an instance could.
And you cannot use raise event to invoke these on instances on layouts.
So, the empty keyup and keydown event handlers on the container make it so the “normal” event handlers on the container are “implemented” – they just do nothing.
And now the controls in the container CAN use RaiseEvent to invoke the newly added KeyDown and KeyUp events
Its a way to work around the fact the ContainerControl already has keydown & keyup
Oh, I think I get it now. It is that the compiler isn’t smart enough to see that the event definition should be called before the build-in event. By adding the build-in one to the ContainerControl – even if it is empty – it is only the one from the event definition that could possibly be called, thereby removing that ambiguity for the compiler.
I have to admit I never looked into the details of why you have to do it this way. I have theories but I cannot confirm them since I’m not at Xojo any longer.
I just know that you do and that it works.
I guess to be completely correct you should actually call the ContainerControl’s event definition from the ContainerControl’s event …
Btw maybe you could add a little marker with the number of comments to your blog, like Bob does? Makes it easy to spot when new ones have been posted …