Larry,
NOTE: When I am using Color below I am largely using it generically to refer
to any value of a class or structure.
Correct, but its the attribute of the object that is desired. They both
return
Me bad, by "comparing the objects themselves" I am referring specifically
to Identity Equals, or equals based on the "value" (aka identity) of an
object, not a reference. Object.Equals represents Identity Equals. When
Object.Equals is overridden in a class or structure that is.
I am saying the identity of the object is preferred over one or more
attributes.
But, that is the object form of the same comparison and would be used in
place of Equals, if Is was allowed to be used on structures.
I can see where others may (incorrectly) think I am referring to "comparing
the object references themselves" Object.ReferenceEquals (Is operator)
represents reference equals (hmm reference types & reference equals must be
a connection). Reference equals happens to be the default for Object.Equals
if you don't override it.
Again:As I stated earlier you are comparing an attribute of said object, not the
actual identity of the object. Yes it just happens that the above two works,
sort of. However can you truly apply the same rule consistently to all
objects (classes or structures)? Are you confident that it will work
consistently with Color all the time? That V2 of Color will not change what
Name returns?
Remember that System.Color.Equals & System.Color.op_Equality both "compares
more than the ARGB values of the Color structures".
Also, remember our friend Encapsulation, one of the major tenets of OO!
Remember Encapsulation says that the object itself should be responsible for
behavior such as comparing itself to another (Object.Equals) rather then
letting code outside of the class do the comparison.
Further picking attributes to compare feels like an example of "Oddball
Solution Smell" which means "When a problem is solved one way throughout a
system and the same problem is solved another way in the same system, one of
the solutions is the oddball or inconsistent solution", Oddball here means
using variable.This, variable.That, and variable.OtherThing to compare
attributes, rather then consistently using variable.Equals to compare object
identities.
Yes using Object.Equals & = operator is inconsistent with each other.
However! they both represent comparing object identities and they *are*
consistent with the framework. Plus as I mention earlier VS.NET 2005 will
allow us to overload the = operator so we can return to being consistent.
Remember that the Framework will use Object.Equals when you use functions
such as ArrayList.IndexOf, Array.IndexOf and other functions that need the
Identity of an object.
Oddball Solution Smell is defined in Joshua Kerievsky's book "Refactoring to
Patterns" from Addison Wesley.
Identity Equals is checking to see if two objects logically contain the same
thing, although physically they are separate objects. Where "object" is
either a reference type or a value type.
For example a Person Object:
Public Class Person
Public FirstName
Public MiddleName
Public LastName
Public Sub New(firstName, middelName, lastName)
...
Public Overloads Function Equals(other As Person) As Boolean
Return (firstName = other.FirstName _
AndAlso middleName = other.middleName _
AndAlso lastName = other.lastName)
End Function
Public Overloads Overrides Function Equals(obj As Object) As Boolean
If TypeOf obj Is Person Then
Return Equals(DirectCast(obj, Person))
Else
Return False
End If
End Function
End Class
Dim
Dim person1 As New Person("Jay", "B", "Harlow")
Dim person2 As New Person("Jay", "B", "Harlow")
Reference Equals (Is operator) says that the person1 & person2 variables are
distinctly separate objects, where as Identity Equals says they logical both
contain the same "person". Person.Equals encapsulates the how two persons
are compared, if we later decide that Person has a distinct Id property
(such as the primary key in the database) Person.Equals can be made to use
that for comparisons or the name if the Person.Id is not yet set.
For example:
Dim person1 As Person = Person.Finder.FromId(1234)
Dim person2 As New Person("Jay", "B", "Harlow")
Person.Finder.FromId sets the Person.Id property in addition to the name
properties, where as the constructor only sets the name properties.
Person.Equals could be smart enough (Strategy Pattern perhaps) to compare
only Person.Id properties if the they are set in both objects, otherwise it
might compare only name properties. I would seriously consider if I would
actually do this or not as it complicates Person.GetHashCode which should be
override when Person.Equals is override so Person plays nicely in
HashTables...
Same with System.Color:
Dim color1 As Color
Dim color2 As Color
Reference Equals (Is Operator) doesn't really make sense as System.Color is
a value type (references are not involved). However Identify Equals does
make sense as System.Color has a distinct Identity, which as far as I can
tell is a culmination of at least Color.Name, Color.ToArgb and Color.IsEmpty
(based on the code I gave last night). Now I could entrust my friend
Encapsulation & ask Color to compare itself to another Color (Object.Equals)
or I can think I am smarter then Color and pick & choose attributes to
compare, which may actually miss aspects of its identity when Color 2.0
arrives.
As I stated earlier if you want to apply the = operator itself to
System.Color in VB.NET 2002 or VB.NET 2003 you can use its overloaded =
operator which is Color.op_Equality.
http://msdn.microsoft.com/library/d...rfSystemDrawingColorClassop_EqualityTopic.asp
VB.NET 2005 will call System.Color.op_Equality for you when you do "color1 =
color2".
An example of why using identity Equals instead of "attribute equals": the
identity of System.DateTime changes from .NET 1.1 to .NET 2.0! In .NET 2.0 a
DateTime "internally represents the concatenated kind and ticks fields as a
single, 64-bit unsigned number."
So using comparing DateTime.Ticks rather then DateTime.Equals to compare two
DateTimes quite possibly introduce inconsistent results when you upgrade.
Luckily VB.NET calls DateTime.Compare when you use the = operator on
DateTime values (I would have expected it to call DateTime.op_Equality). I
am in the process of rebuilding my VB.NET 2005 machine so I have not tried
it.
http://msdn2.microsoft.com/library/03ybds8y.aspx
Hope this helps
Jay