= vs IS

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 !"
  System.debuglog "d1 = d2 => FALSE !"
End If

If d1 Is d2 Then
  System.debuglog "d1 IS d2 => true !"
  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 !

8 Replies to “= vs IS”

  1. 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.

    1. 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

  2. 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?



    1. 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

  3. 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.

  4. 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.

  5. 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 …

Comments are closed.