15.02.2015 Views

C# 4 and .NET 4

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

162 ❘ ChaPTer 7 OperAtOrs And cAsts<br />

ComParing objeCTs for equaliTy<br />

After discussing operators <strong>and</strong> briefly touching on the equality operator, it is worth considering for a<br />

moment what equality means when dealing with instances of classes <strong>and</strong> structs. Underst<strong>and</strong>ing the<br />

mechanics of object equality is essential for programming logical expressions <strong>and</strong> is important when<br />

implementing operator overloads <strong>and</strong> casts, which is the topic of the rest of this chapter.<br />

The mechanisms of object equality are different depending on whether you are comparing reference types<br />

(instances of classes) or value types (the primitive data types, instances of structs or enums). The following<br />

sections present the equality of reference <strong>and</strong> value types independently.<br />

Comparing reference Types for equality<br />

You might be surprised to learn that System.Object defines three different methods for comparing objects<br />

for equality: ReferenceEquals() <strong>and</strong> two versions of Equals(). Add to this the comparison operator<br />

(==), <strong>and</strong> you actually have four ways of comparing for equality. Some subtle differences exist between the<br />

different methods, which are examined next.<br />

The referenceequals() Method<br />

ReferenceEquals() is a static method that tests whether two references refer to the same instance<br />

of a class, specifically whether the two references contain the same address in memory. As a static<br />

method, it is not possible to override, so the System.Object implementation is what you always have.<br />

ReferenceEquals() will always return true if supplied with two references that refer to the same object<br />

instance, <strong>and</strong> false otherwise. It does, however, consider null to be equal to null:<br />

SomeClass x, y;<br />

x = new SomeClass();<br />

y = new SomeClass();<br />

bool B1 = ReferenceEquals(null, null);<br />

bool B2 = ReferenceEquals(null,x);<br />

bool B3 = ReferenceEquals(x, y);<br />

The virtual equals() Method<br />

// returns true<br />

// returns false<br />

// returns false because x <strong>and</strong> y<br />

// point to different objects<br />

The System.Object implementation of the virtual version of Equals() also works by comparing<br />

references. However, because this method is virtual, you can override it in your own classes to compare<br />

objects by value. In particular, if you intend instances of your class to be used as keys in a dictionary,<br />

you will need to override this method to compare values. Otherwise, depending on how you override<br />

Object.GetHashCode(), the dictionary class that contains your objects will either not work at all or will<br />

work very inefficiently. One point you should note when overriding Equals() is that your override should<br />

never throw exceptions. Once again, this is because doing so could cause problems for dictionary classes<br />

<strong>and</strong> possibly certain other .<strong>NET</strong> base classes that internally call this method.<br />

The static equals() Method<br />

The static version of Equals() actually does the same thing as the virtual instance version. The difference<br />

is that the static version takes two parameters <strong>and</strong> compares them for equality. This method is able to cope<br />

when either of the objects is null, <strong>and</strong>, therefore, provides an extra safeguard against throwing exceptions<br />

if there is a risk that an object might be null. The static overload first checks whether the references it has<br />

been passed are null. If they are both null, it returns true (because null is considered to be equal to<br />

null). If just one of them is null, it returns false. If both references actually refer to something, it calls the<br />

virtual instance version of Equals(). This means that when you override the instance version of Equals(),<br />

the effect is as if you were overriding the static version as well.<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!