The Operator "=" is not defined for type "Object" and type "Object"

rbulph

Junior Contributor
Joined
Feb 17, 2003
Messages
397
The Operator "=" is not defined for type "Object" and type "Object"

The following code doesn't work:

Visual Basic:
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim a As New Object
        Dim b As New Object
        a = b
        Dim c As New Object

        Select Case a
            Case b
                Text = "a is b"
            Case c
                Text = "a is c"
        End Select
    End Sub
End Class

because "The Operator "=" is not defined for type "Object" and type "Object"". This seems like a missed opportunity to provide a useful capability in the language. There's no way around this is there, apart from doing "If a is b then ... elseif a is c then..."?
 
Forgive me, but I'm not sure on the specifics for this (I haven't had time to look it up), but the following will work in place of using Select Case...
Visual Basic:
If a Is b Then
    ....
ElseIf a Is C Then
    ....
End If
Regards,
Paul.
 
Mandelbrot is correct. Use the "Is" keyword instead of "=". Had to fix the same problem in some code I converted last night and that is what solved it.
 
Not sure that some of you have undestood what I was originally asking. I'm well aware that you can use a series like "If, ElseIf, ElseIf...End If", but if the reference for the object you want to check is quite lengthy (e.g you need to go down a long chain of properties to get to it) then you have to either declare a new variable to refer to it before you call the conditions, or keep getting the reference to it in each condition. I suppose the former is OK, but I was after a way to use Select Case, as this would be easiest to read. I've since found that you can in fact use a Select Case structure for your own objects provided you define an = and a <> operator for them as follows:

Visual Basic:
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim g As New abc
        Dim h As New abc
        Dim p As abc = h

        Select Case p
            Case g
                Text = "p is g"
            Case h
                Text = "p is h"
        End Select

    End Sub
End Class


Public Class abc
    Public Shared Operator =(ByVal a As abc, ByVal b As abc) As Boolean
        Return a Is b
    End Operator
    Public Shared Operator <>(ByVal a As abc, ByVal b As abc) As Boolean
        Return Not (a = b)
    End Operator
End Class
 
You can compare like this using op_equality and related operator overloads. Alternatively, you can implement IComparable on your object and return the appropriate comparisons...
Visual Basic:
Class MyObject
    Implements IComparable
...
    Public Function CompareTo(pObject As Object) Implements IComparable.CompareTo
        Return AnyProperty.CompareTo(DirectCast(pObject, MyObject).AnyProperty)
    End Function
...
End Class
This returns a negative to positive response based on wether the specified item is less than, equal to or greater than the specified argument.

I would think that the operator overloading would be more the thing you are looking at, but I don't use it if I can help it (some see it as bad practice, others don't - your views are your own).

I haven't personally checked the differences in speed between a Select Case and If ElseIf construct, but if there is a difference, I don't believe it would be huge. Obviously Select Case does provide a higher degree of readability, but this could be taken away by overloading your operators...

I believe MarbleEater and PlausiblyDamp could give you a more detailed/in-depth explanation than I due to experience and training, and I'm sure, also, that if you searched the forum you'd find what you're looking for.

One fantastic construct (as available in VB6) is the With ... End With construct - helps to cut down on the typing!


Sorry I couldn't be of more help,
Paul.
 
PlausiblyDamp said:
Just curious as to why you need to be doing so many object equality checks that this is an issue...
I have an object and I want to do different things depending on what type it is. Rather than say "If TypeOf x is class 1, elseif TypeOf x is class2 etc.", it would be good if it could say "Select Case x.GetType, Case GetType(Class1), Case GetType(Class2) etc.". That's all. It's not a big issue at all.
 
Just that you might be better off if all the objects implemented a single interface / inherited from a base class as this would remove the need for lots of explicit checks regarding object types.
 
PlausiblyDamp said:
Just that you might be better off if all the objects implemented a single interface / inherited from a base class as this would remove the need for lots of explicit checks regarding object types.
They do all inherit from a single base class. The reference I have is to a base class object and then I'm performing the check to see what type of inheriting object it is.

But I see what you mean - I could give the base class a procedure and override it in each of the inheriting classes to do whatever I'm currently doing for that class in my type checking routine. Then just call that procedure instead of checking the type. Yes, I suppose that's a good point. It would be better encapsulation.
 
The IComparer example that I showed before, actually, perfectly highlights the use of an interface. You don't have to compare everything the same way - you might want to compare a particular object's ID property as opposed to it's Name property. By implementing the comparer class you're forcing your implementing class to have this method incorporated, and will be able to utilise this method as and when, despite it's programmatic contents.

For instance:
Visual Basic:
Public Interface IRequiredMethod

    Function MustDo()

End Interface

Public Class NewShinyClass
    Implements IRequiredMethod
...
    Public Function MustDo() Implements IRequiredMethod.MustDo
    ...
    End Function
...
End Class
Now we have a new shiny class that can do lots of other things, but must provide support for the specified method.

We can implement this elsewhere in the code like so...
Visual Basic:
...
Dim reqObject As IRequiredMethod = MyExistingObjectCollection.Item(loopCounter)
reqObject.MustDo()
...
That way there's no need to even bother with Select Case or If Is Then...


Paul.
 
Yeah, I understand interfaces, but I think I prefer to do this with an overriden procedure in the base class, since I already have this structure, so as to avoid having to create a new interface.
 
PlausiblyDamp said:
Just that you might be better off if all the objects implemented a single interface / inherited from a base class as this would remove the need for lots of explicit checks regarding object types.

Actually I don't entirely accept this. Suppose you're using an object system to model a real world situation, and you have a facility for plug-ins to examine those objects. They may need to know what type of object they have in order to take appropriate action. They're not examining the type of the object in order to call one of its methods. They 're just examining it to get information about the situation presented to them. It would be much simpler if they could use a "Select Case Object.GetType" structure than an "If Then, ElseIf" structure. But it seems this isn't possible, unless there's some way that I can define the "=" operator for the System.Type type, and I can't find such a way.
 
Hi rbulph


I can't see your problem there. Personally, as I see it, everything you have said just re-enforces the need to implement interfaces. By providing a core operations set using an interface within your own programs, any external plug-ins or tools then know what to expect.

It's impossible to write a blind plug-in - that's like writing a spreadsheet splitting utility for WinAmp...... If you can identify that a connection with a particular program or suite of programs is necessary, then you're going to want to know the form of the data that's going to be spat out by it, and what better way than using an interface.


Paul.
 
Last edited:
mandelbrot said:
Hi rbulph


I can't see your problem there. Personally, as I see it, everything you have said just re-enforces the need to implement interfaces. By providing a core operations set using an interface within your own programs, any external plug-ins or tools then know what to expect.

It's impossible to write a blind plug-in - that's like writing a spreadsheet splitting utility for WinAmp...... If you can identify that a connection with a particular program or suite of programs is necessary, then you're going to want to know the form of the data that's going to be spat out by it, and what better way than using an interface.


Paul.

I'm not trying to write a blind plug-in. The plug-in expects an object of a certain base type. As I say, I'm using the class structure to represent real world information. The plug-in receives the object through the interface. The plug-in then determines which out of various classes that implement the base type the object is. Maybe it also examines some properties of the object. It then returns information accordingly. It never calls any methods of the object. Having an interface to do this for each type of object would require the functionality of the plug-in to go into the class library, which would defeat the purpose of having a plug-in.
 
rbulph said:
The plug-in expects an object of a certain base type.
So the argument against using an interface would be...? Obviously you'd still be using a class to represent your object, but the data fed to the plug-in could be interpreted using the interface.

What if the plug-in doesn't actually recognise the class that you've posted to it? This could come about due to revisions to the core program or even the plug-in itself. If the program still posts its data to the plug-in using an interface, however, the plug-in will be able to recognise the output. In fact, you could use more than one interface, the first (primary) representing the generalised class, and the second being a more specialised interface relating to a setting within the primary interface.

You seem to be set on your path, though, rbulph. You will have problems with Select Casing a particular object type. The only workaround to this is to define a property within the class that identifies it as a particular object type, then Select Case on that...
Visual Basic:
Select Case myObject.Class
    Case ClassTypes.Class1
    Case ClassTypes.Class2
    Case ClassTypes.Class3
End Select
It's up to you...


Paul.
 
mandelbrot said:
So the argument against using an interface would be...?
An interface is implemented by the plug-in to receive the object. But you can't have the objects implement an interface to do what the plug-in is to do, and so avoid any demand for a Select Case structure in the plug-in, because they are defined in the class library, not the plug-in.

mandelbrot said:
What if the plug-in doesn't actually recognise the class that you've posted to it? This could come about due to revisions to the core program or even the plug-in itself. If the program still posts its data to the plug-in using an interface, however, the plug-in will be able to recognise the output.
Again, the program does post its data to the plug-in using an interface. If a new class is introduced it will have to derive from the base class used to declare the parameter sent to the plug-in through the interface. The plug-in won't recognise this, so will probably do nothing with it, because the Select Case won't catch it. What more could you expect?

mandelbrot said:
You seem to be set on your path, though, rbulph.
I see no choice. Having to work around not being able to use Select Case is not such a big deal. Thanks for your input anyway.
 
Ok, it sounds like you don not have full control over all the objects in question, particularly those of the .NET Framework itself, so requiring an interface would not help here.

Your idea to overload "=" and "<>" would work, but you'd need to pre-define this for all objects in question against a custom class that you create. Do-able, but I don't know that it's worth the extra time to do all this just to create a "slick" 'Select Case' statement instead of a compound 'If..ElseIf...ElseIf...' statement. But this absolutely would work.

The only real problem that I see with this is that this is such a non-standard use that anyone else looking at your code would likely be thrown. The "=" comparison is normally overloaded for structures and is meant to return 'True' in a cloned situation; however the "Is" operator is defined to return 'False' in a cloned situation and is a true object identifier. By overloading the "=" operator in this manner, you are redefining it to be an object identifier and so your Select Case statement, while clear to you, could easily throw other programmers when trying to read it. I realize that in C# the "==" operator is in-fact used for both structure equality and object identity, but VB.NET has other expectations, and I'm not sure that you should be changing it just for your own code.

What you are trying to accomplish is usually done is to use 'Select Case True' and then put whatever condition you want within each check:
Visual Basic:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim g As New abc
    Dim h As New abc
    Dim p As abc = h

    Select Case True
        Case p Is g
            Text = "p is g"
        Case p Is h
            Text = "p is h"
     End Select
End Sub
Admitedly, not as slick as what you were trying to do, but it's not bad and the operations themselves are exposed, not hidden away somewhere within an operator overload definition within the 'abc' class...

Just a thought! I do like your thinking here, a lot, but Select Case is designed for value or "clone" equality, not object identification testing and your overloads "=" approach could really throw other people trying to read your code.

Mike
 
Mike_R said:
Your idea to overload "=" and "<>" would work, but you'd need to pre-define this for all objects in question against a custom class that you create. Do-able, but I don't know that it's worth the extra time to do all this just to create a "slick" 'Select Case' statement instead of a compound 'If..ElseIf...ElseIf...' statement. But this absolutely would work.

I don't think it is do-able because I'm not looking at determining identities of objects of my classes but identities of objects of the System.Type class. If I could define "=" and "<>" for the Type class that would be all I'd need to do, but I don't think this is possible unfortunately.

Your "Select Case True" idea is good though, and a definite improvement on an "If, ElseIf" structure, so thanks for that.
 
Back
Top