"==" not symmetric

Lionello Lunesu lio at lunesu.remove.com
Wed May 24 00:07:44 PDT 2006


Going thirty and I'm still mixing left and right :S

You've made some good points. Indeed, since opEquals has to check the 
type of the passed Object, it'll automatically check for null too.

Still odd though, that you can get a different result when you do o1==o2 
or o2==o1, but I guess the library programmer should take care of that :)

L.

Unknown W. Brackets wrote:
> Bad means a pointer to an invalid object.  A bad pointer.  I was trying 
> to cover all the bases.
> 
> Your typical opEquals looks like this:
> 
> bool opEquals(Object o)
> {
>    Foo f = cast(Foo) o;
> 
>    // If o was null, or if f is now null (doesn't match class) fail.
>    if (f is null)
>       return false;
> 
>    return f.prop == this.prop;
> }
> 
> Anything else either doesn't work properly with subclassing, isn't 
> typesafe, or will segfault.  This doesn't seem wrong to me.
> 
> Okay, missed that x and y were supposed to be objects.  You seem to be 
> missing a "x y" case, then.  This would be the same as "y x", though.
> 
> It would be a bad idea to check the class info imho.  Why can't a XYZ 
> equal an ABC even if they share no parents aside from Object?  But that 
> does mean the order of the comparison does matter (consider Array == 
> SpecializedArray vs. SpecializedArray == Array.)
> 
> No, opEquals should never begin with any check on lhs... lhs will be 
> this.  It should however check rhs, first casting it more than likely, 
> and then checking for null on the cast.... since, if the cast fails, it 
> will be null.
> 
> This same check cannot be necesarily made in ==, since it can't know 
> what other classes the opEquals supports.
> 
> Still, checking for null could be a good thing for sanity; I'd guess it 
> doesn't because opEquals would have to anyway.
> 
> -[Unknown]
> 
> 
>> 'bad'? I don't think you can tell whether a pointer is bad or valid. I 
>> think calling opEquals(null) is bad, since it's likely to crash. And 
>> I've noticed before that many implementations start with a if(lhs is 
>> null) check. It just makes sense to put that check 1 function up in 
>> the code, namely in the ==.
>>
>>> I don't know what "y" is on your table.
>>
>> 'y' is just different from 'x' :)
>>
>>
>> Might not be a bad idea to also check the classinfo of both objects in 
>> the == ?
>>
>>> So, okay... the only differences we have:
>>>
>>> If o1 is null, reversing the comparison will depend on opEquals 
>>> returning false when it is passed a null pointer (which should be the 
>>> case.)
>>
>> Right. At the moment opEquals _must_ begin with "if (lhs is null) 
>> return false;", but this can easily be enforced by putting the same 
>> check in ==.
>>
>>> Comparing a valid pointer to a bad pointer cannot be properly 
>>> reversed, or it might cause a segfault.  This is always wrong anyway 
>>> imho.
>>
>> Right. Nothing you can do about that I'm afraid.
>>
>>> That said, opEquals (imho) will either always check for null or 
>>> cannot be reversed (null == evaluatesToNullObject is always false.)  
>>> So it would seem logical to do something like you suggested.
>>
>> It would seem so :)



More information about the Digitalmars-d mailing list