Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / February 2008

Tip: Looking for answers? Try searching our database.

Overriding operators

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Microsoft Newsserver - 19 Feb 2008 11:23 GMT
Hi

I have a class which I have overridden the operators and it woks fine. But
when I try and test for the following. It fails. I need to know how to test
equality for Nulls, before I test for the euqlity of the object, how can I
do this ?

MyClassInstance=null;

if( MyClassInstance!=null )
{

    still gets

}
Marc Gravell - 19 Feb 2008 11:38 GMT
Are you looking for ReferenceEquals(MyClassInstance, null) ?

However, your example is confusing - looks to me like a very confusing
operator implementation if a null instance reports itself as not equal to
null... can't say more without looking at the operator code.

Marc
Microsoft Newsserver - 19 Feb 2008 11:43 GMT
Hi Marc

Thanks for your reply. This is some of the implementation. Basically the
equality test is working ok when the class has been instantiated.
Unfortuneatly, when I have set the class to = null; and I want to test that,
it fails of course, and I need to know how to properly code it so I can test
for a null value as the overloads are static.  I have tried to test s1,s2
for nulls, but of course I get a stack overflow exception. Operator
overloading isnt something ive dont much of before so yoru advice is
helpful.  I tried the referenceequals function but that fails in my
scanario.

Many thanks.

public override int GetHashCode()

{

return base.GetHashCode();

}

public override bool Equals(object obj)

{

return base.Equals(obj);

}

//Operator Overrides - ( Duration Comparison )

public static bool operator ==(Slot s1, Slot s2)

{

if (s1.startTimeID == s2.startTimeID && s1.endTimeID == s2.endTimeID)

return true;

else return false;

}

> Are you looking for ReferenceEquals(MyClassInstance, null) ?
>
[quoted text clipped - 3 lines]
>
> Marc
Marc Gravell - 19 Feb 2008 12:03 GMT
OK; that is going to break when nulls are involved, so simply deal with
those separately (see below); most of the code is AreEqual - first we handle
"are they the same instance" (which also handles "are they both null") - if
so, must be the same. Then if *either* is null (by itself) then they can't
be equal. So now we've excluded every case involving null; *now* we can
worry about the field equality.

Note also that I've made Equals() consistent with these rules (reports false
if it is compared to something that isn't a Slot), and I've provided a
meaningful hash implementation (so you can use the object in a
dictionary/hashtable).

Does that work any better? To be honest, I'm not 100% sure how far you got,
so rather than me prattle on, if you have any specific questions, please
ask?

Marc

using System;
class Slot : IEquatable<Slot>
{
   private int startTimeId, endTimeId;
   public override int GetHashCode()
   {
       return (17 * startTimeId.GetHashCode()) + endTimeId.GetHashCode();
   }

   public override bool Equals(object obj)
   {
       Slot slot = obj as Slot;
       return slot == null ? false : AreEqual(this, slot);
   }
   public bool Equals(Slot slot)
   {
       return AreEqual(this, slot);
   }

   private static bool AreEqual(Slot s1, Slot s2)
   {
       if (ReferenceEquals(s1, s2)) return true;
       if (ReferenceEquals(s1, null)
           || ReferenceEquals(s2, null)) return false;

       return s1.startTimeId == s2.startTimeId
           && s1.endTimeId == s2.endTimeId;
   }
   public static bool operator ==(Slot s1, Slot s2)
   {
       return AreEqual(s1, s2);
   }
   public static bool operator !=(Slot s1, Slot s2)
   {
       return !AreEqual(s1, s2);
   }
}
Jon Skeet [C# MVP] - 19 Feb 2008 12:06 GMT
> Thanks for your reply. This is some of the implementation. Basically the
> equality test is working ok when the class has been instantiated.
[quoted text clipped - 5 lines]
> helpful.  I tried the referenceequals function but that fails in my
> scanario.

ReferenceEquals *is* what you're after, so could you post a short but
complete program which demonstrates the problem, attempting to use
ReferenceEquals?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by "short but complete program".

(I have to say that overloading == but leaving Equals and GetHashCode
doing their original comparisons is somewhat confusing behaviour.)

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Hans Kesting - 19 Feb 2008 12:10 GMT
see inline

> public override bool Equals(object obj)
>
> {

    if ( obj == null || ! (obj is Slot))
       return false; // "Slot" (this) against non-Slot: fail

    Slot other = (Slot)obj;
    // and now compare similar to the == operator

> }
>
[quoted text clipped - 3 lines]
>
> {

  if (s1 == null && s2 == null)
     return true; // both null: so equal
  if (s1 == null || s2 == null)
     return false; // one is null, the other not: not equal

> if (s1.startTimeID == s2.startTimeID && s1.endTimeID == s2.endTimeID)
>
[quoted text clipped - 3 lines]
>
> }

Hans Kesting
Microsoft Newsserver - 19 Feb 2008 12:07 GMT
Thanks guys.

I will look into this further having read your replies and get back to you,
thank you very much for your assistance.

> see inline
>
[quoted text clipped - 30 lines]
>
> Hans Kesting
Jon Skeet [C# MVP] - 19 Feb 2008 12:18 GMT
> > //Operator Overrides - ( Duration Comparison )
> >
[quoted text clipped - 4 lines]
>    if (s1 == null && s2 == null)
>       return true; // both null: so equal

Bang! Stack overflow. The above will call operator == again, recursing.
You need to either cast to object, or use object.ReferenceEquals. I
personally find the latter more explicit.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Microsoft Newsserver - 19 Feb 2008 12:32 GMT
This seems to work ok, thank you all for your help.

//Operator Overrides - ( Duration Comparison )

public static bool operator ==(Slot s1, Slot s2)

{

if (ReferenceEquals(s1, null) && ReferenceEquals(s2, null)) return true;

if (!ReferenceEquals(s1, null) && ReferenceEquals(s2, null)) return false;

if (s1.startTimeID == s2.startTimeID && s1.endTimeID == s2.endTimeID)

return true;

else return false;

}

public static bool operator !=(Slot s1, Slot s2)

{

if( ReferenceEquals(s1, null) && ReferenceEquals(s2,null)) return false;

if( !ReferenceEquals(s1, null) && ReferenceEquals(s2,null)) return true;

if (s1.startTimeID != s2.startTimeID || s1.endTimeID != s2.endTimeID)

return true;

else return false;

}

>> > //Operator Overrides - ( Duration Comparison )
>> >
[quoted text clipped - 8 lines]
> You need to either cast to object, or use object.ReferenceEquals. I
> personally find the latter more explicit.
Marc Gravell - 19 Feb 2008 12:42 GMT
For the record - there is a reason that the compiler warning prompts you to
override Equals() and GetHashCode() - so you really should provide something
sensible here.
Also, to reduce maintenance overhead, I do recommend only having the "real"
code once (rather than separately in == and !=) - you could call one from
the other, for example (and simply negate the result).

Marc
Microsoft Newsserver - 19 Feb 2008 12:44 GMT
noted.

Thank you.

> For the record - there is a reason that the compiler warning prompts you
> to override Equals() and GetHashCode() - so you really should provide
[quoted text clipped - 4 lines]
>
> Marc
Ben Voigt [C++ MVP] - 19 Feb 2008 19:29 GMT
> This seems to work ok, thank you all for your help.
>
[quoted text clipped - 6 lines]
> if (ReferenceEquals(s1, null) && ReferenceEquals(s2, null)) return
> true;

instead:

if (ReferenceEquals(s1, s2)) return true;

> if (!ReferenceEquals(s1, null) && ReferenceEquals(s2, null)) return
> false;

That needs to be ||, not &&

> if (s1.startTimeID == s2.startTimeID && s1.endTimeID == s2.endTimeID)
>
[quoted text clipped - 7 lines]
>
> {

instead:

return !(s1 == s2);

> if( ReferenceEquals(s1, null) && ReferenceEquals(s2,null)) return
> false;
[quoted text clipped - 26 lines]
>> http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
>> World class .NET training in the UK: http://iterativetraining.co.uk
Jeroen Mostert - 19 Feb 2008 18:19 GMT
> see inline
>
[quoted text clipped - 3 lines]
>>
>     if ( obj == null || ! (obj is Slot))

No. This should be

if (obj == null || obj.GetType() != this.GetType())

because Slot is a class, and "is" returns true for any class derived from
Slot too. It is possible the comparison defined in Slot is still correct for
derived classes, but there's no reason to force it to be.

If the derived class adds fields and overrides .Equals to compare for these,
using "is" becomes flat-out wrong, because it could mean that
aSlot.Equals(aDerivedSlot) is true but aDerivedSlot.Equals(aSlot) is false,
which breaks the contract for .Equals().

Using "is" does work for structs and sealed classes, but even there
.GetType() isn't wrong.

Signature

J.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.