views:

875

answers:

1

Fixed: See notes at bottom

I am implementing a generic class that supports two features, implicit type conversion and custom equality operators. Well, it supports IN-equality as well, if it does that.

1) if ( "value" = myInstance ) then ...
2) Dim s As String = myInstance
3) Dim s As String = CType(myInstance,String)

The problem I am having is that if I support #2, implicit conversion, then I can't get my equality operators to work, since they complain about no conversion being the most specific.

The error I get is this (simplified a bit for brevity):

Overload resolution failed because no accessible '=' is most specific for these arguments:
    'Public Shared Operator =(obj As MyClass, data As String) As Boolean': Not most specific.
    'Public Shared Operator =(data As String, obj As MyClass) As Boolean': Not most specific.
    'Public Shared Operator =(obj1 As MyClass, obj2 As MyClass) As Boolean': Not most specific.

What is the best way of implementing this. Just as importantly, what should I leave out? I have implemented the following conversions

Operator =(ByVal data As String,    ByVal obj  As classType) As Boolean (and <>)
Operator =(ByVal obj  As classType, byval data As String) As Boolean (and <>)
Operator =(ByVal obj1 As classType, ByVal obj2 As classType) As Boolean (and <>)
Equals(obj as Object) as Boolean
Equals(compareTo as classType ) as Boolean
Equals(compareTo as String) as Boolean
Widening Operator CType(ByVal source As String) As classType
Widening Operator CType(ByVal source As classType) as String
Narrowing Operator CType(ByVal inst As classType) As dataType

In my widening operator I do some reflection, which is why I wanted to be able to do an implicit convert DOWN to String when I do a comparison or assignment with the string on the left side.

A) SomeObject.StringPropertySetter = MyClass

Fix (edit)

I went way overboard in what I implemented, because I didn't understand what was happening. Comparison between the base types (ie string/double/guid) takes place via the widening ctype(...) as String (or Guid,etc) operator. In the end, i just implemented these functions and all my test cases still pass, in addition to assignment from the class to a base type instance

Public Class MyClass(Of BaseType)

    Widening Operator CType(ByVal source As dataType) As MyClass 
    Widening Operator CType(ByVal source As MyClass) As dataType //conv between inst & base
    Equals()  // for datatype, classType, object
    Operator <>(MyClass,MyClass) // for comparison between two instances
    Opeator   =(MyClass,MyClass)

comments are c style, but code is vb.net

Of course the class is a little more complicated than that, but that give me everything I needed :)

+2  A: 

You should not override the = operator. If you have implicit conversions to types such as string or int, then let the default equality operator take over.

As a general rule, if you need to customize equality for a class you should override the Equals(object) method.

Joseph Daigle