Note: The code samples are based on Part I of the series.
This method returns “True” if both objects have the same value. The default implementation of this method checks if two reference type objects point to the same object. Now this isn’t always the desired behavior. In many cases you want to compare the value(s) of a property/ies within your object to let you know if you’re dealing with the same object. To show the default implementation, I will create two instances of the Car-class with the same values for the properties:
1: private Car car1 = new Car("blue", 4, "Volkswagen", "Golf");
2: private Car car2 = new Car("blue", 4, "Volkswagen", "Golf");
Then compare these objects:
car1.Equals(car2)
Gives as output: False.
Now we know that the parameters are exactly the same, but of course, these are two separate instances of the Car-class so the references are different. Now let’s say we wish to compare these cars based on their properties. This will require me to do my own implementation of the Equals()-method. You probably have noticed that the default implementation takes an object of type Object as a parameter. In my own implementation I will also provide a type-safety, meaning that if I want to compare two objects, the object I give as a parameter is of the same type as the object I’m calling the Equals() from.
So I add the following code to the Car-class:
1: public override bool Equals(object obj)
2: {
3: Car c = obj as Car;
4:
5: if(c != null)
6: {
7: if (this.Brand == comp_obj.Brand &&
8: this.Color == comp_obj.Color &&
9: this.Model == comp_obj.Model &&
10: this.NumberOfSeats == comp_obj.NumberOfSeats)
11: {
12: return true;
13: }
14: }
15: return false;
16: }
When I execute the program again, the output now is “True”. Since every property of the car is the same, we can assume that both objects concern the same car. Now think about a car company/dealership/leasing company/… They have probably many cars with the same properties. So it’s interesting here to also have something unique about every car to add to your car-object. A license plate is probably not a good idea since a car that just got off the production chain hasn’t got a license plate yet. Maybe the chassis number is a better idea (In reality that is a 17-character combination of digits and letters, for the ease of the example, let’s keep it an integer).
Adding the new property to the car-class:
1: private int chassisNumber;
2:
3: public int ChassisNumber
4: {
5: get { return chassisNumber; }
6: set { chassisNumber = value; }
7: }
Refactoring the Equals() method:
1: public override bool Equals(object obj)
2: {
3: Car c = obj as Car;
4:
5: if(c != null)
6: {
7: if (this.ChassisNumber == comp_obj.ChassisNumber )
8: {
9: return true;
10: }
11: }
12:
13: return false
14: }
When you run the program again, the output is “False”, which is correct since we are talking about two different cars with the same properties.
A good implementation of the Equals() method can help you a great deal when sorting or searching a collection of objects. To help define what a “good” implementation is, MSDN defines a set of rules that your implementation must obey to:
· x.Equals(x) returns true, except in cases that involve floating-point types. See IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems.
· x.Equals(y) returns the same value as y.Equals(x).
· x.Equals(y) returns true if both x and y are NaN.
· (x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.
· Successive calls to x.Equals(y) return the same value as long as the objects referenced by x and y are not modified.
· x.Equals(null) returns false
· Implementations of Equals must not throw exceptions