Comparing Empty Value types

G

Guest

I have a public variable in a class of type color declared as follows:

public mycolor as color = color.Empty

I want to check to see if the user has specified a color like;

if mycolor = Color.Empty then.....
or
if mycolor is Color.Empty then .......

I get errors saying that = can be used for colors and is can't be used with
value types. I give up...how do I do this. Thanks.
 
I

Imran Koradia

Since ValueType derives from Object, you can use the Equals method. For
Value Types, this returns true if the instances are of the same type and
have the same value.

If mycolor.Equals(Color.Empty) Then
MessageBox.Show("mycolor is Empty")
End If

hope that helps..
Imran.
 
J

Jay B. Harlow [MVP - Outlook]

Dennis,
Did you try the Equals function or the Equals Operator?

If mycolor.Equals(Color.Empty) Then

End If

To use the Equals Operator you need to call the shared function that is
created.

If Color.op_Equality(mycolor, Color.Empty) Then

End If

See the Color.Equals function in the online help for some important remarks
about using Color.Equals and when you may want to use Color.ToArgb to
compare two colors.

If mycolor.ToArgb() = Color.Empty.ToArgb() Then

End If


NOTE: VS.NET 2005 (aka Whidbey, due out later in 2005) will support calling
the Equals Operator with the familiar "=" syntax. For information on VS.NET
2005 see http://lab.msdn.microsoft.com/vs2005/.

' VS.NET 2005 sample
If mycolor = Color.Empty Then

End If

Hope this helps
Jay
 
H

Herfried K. Wagner [MVP]

Cor Ligthert said:
As alternative
If mycolor.ToArgb = mycolor.Empty.ToArgb

This only works for 'Color'. I would stick with the more general pattern of
using 'Equals'...
 
C

Cor Ligthert

"Herfried K. Wagner [MVP]"
This only works for 'Color'. I would stick with the more general pattern
of using 'Equals'...

You are free to do that. I will not blaim you for that.

However I use this one, I find it nicer just a personal choise

May I do that as well?

:)

Cor
 
J

Jay B. Harlow [MVP - Outlook]

Cor (& Herfried),
As I stated in my initial reply:
See the Color.Equals function in the online help for some important
remarks about using Color.Equals and when you may want to use Color.ToArgb
to compare two colors.

If I want to compare what is visible seen I will use Color.ToArgb in other
words to compare the Alpha, Red, Green & Blue values.

If I want to compare what is literally used I will use Color.Equals or
Color.op_Equality, in other words to compare the names of the color or the
values for unnamed colors.

For example:

Dim color1 As Color = Color.Black
Dim color2 As Color = Color.FromArgb(0,0,0)

Both are visibly Black, however they are not logically the same value. In
other words:

If color1.Equals(color2) Then
' color1 is the same named color as color2
End If

If color1.ToArgb() = color2.ToArgb() Then
' color1 & color2 have the same Alpha, Red, Green & Blue values
End If

Just a thought
Jay
 
C

Cor Ligthert

Jay,

It was just an alternative, this one is not real very important for me,
however I like more evaluating for equality using the = operator than
evaluating using a methode and with the color that is possible.

But the "Is" in this functions tells it very good, therefore it is not
really that important for me.

However as I said, just an alternative.

Cor
 
J

Jay B. Harlow [MVP - Outlook]

Cor,
It was just an alternative, this one is not real very important for me,

Obviously I know its an alternative, Hopefully you noticed that I stated
last night it was an alternative & again just now.

Thanks for noticing.
Jay



Cor Ligthert said:
Jay,

It was just an alternative, this one is not real very important for me,
however I like more evaluating for equality using the = operator than
evaluating using a methode and with the color that is possible.

But the "Is" in this functions tells it very good, therefore it is not
really that important for me.

However as I said, just an alternative.

Cor
 
H

Herfried K. Wagner [MVP]

Jay,

Jay B. Harlow said:
For example:

Dim color1 As Color = Color.Black
Dim color2 As Color = Color.FromArgb(0,0,0)

Both are visibly Black, however they are not logically the same value. In
other words:

If color1.Equals(color2) Then
' color1 is the same named color as color2
End If

If color1.ToArgb() = color2.ToArgb() Then
' color1 & color2 have the same Alpha, Red, Green & Blue values
End If

That's a valid point, and the way to go depends on the situation.
 
J

Jay B. Harlow [MVP - Outlook]

Cor (& others),
however I like more evaluating for equality using the = operator than
So do I, however I want to be certain I know what I am actually comparing &
what I am "slicing" off.

If I use Color.ToArgb to compare the colors I loose comparing the names of
the colors.


Further! As I stated last night in VB.NET 2005 you can use the = operator to
compare colors, it will give you the same result as Color.Equals &
Color.op_Equality, not Color.ToArgb.

So if you want your code to be consistent from VB.NET 2002 to VB.NET 2005
what each method actually does is something to be aware of.

I do find it kind of odd that Color does not have a shared Color.Compare
method, but it has an overloaded = operator.

Hope this helps
Jay

Cor Ligthert said:
Jay,

It was just an alternative, this one is not real very important for me,
however I like more evaluating for equality using the = operator than
evaluating using a methode and with the color that is possible.

But the "Is" in this functions tells it very good, therefore it is not
really that important for me.

However as I said, just an alternative.

Cor
 
C

Cor Ligthert

Jay,

Sorry I missed that you already had given that, I would not have sent my
message than.

However strange that Herfried has put only at my message that reply.

:)

However my excuse is true

Cor
 
G

Guest

Thanks all for the replies and lively discussion. I should have been able to
figure it out myself but after a couple of hours of trying, one tends to
admit their ignorance and seek help.

At least though, I've noticed a few of my questions on this newsgroup has
stimulated lively discussions and that's great for people like me to learn
the various aspects of vb.net. Thanks again all.
 
L

Larry Serflaten

Jay B. Harlow said:
If I want to compare what is literally used I will use Color.Equals or
Color.op_Equality, in other words to compare the names of the color or the
values for unnamed colors.

For example:
If color1.Equals(color2) Then
' color1 is the same named color as color2
End If

If color1.ToArgb() = color2.ToArgb() Then
' color1 & color2 have the same Alpha, Red, Green & Blue values
End If

But you then end up with different syntax for the same type of operation.
Another alternative for the Equals method would be to compare the Name
value itself:

If color1.Name = color2.Name Then
' color1 is the same named color as color2
End If

Although I have a hard time thinking of a situation where I would want to
make that comparison.... ;-) (What do you use it for?)

LFS
 
G

Guest

If you are asking me what I use the comparision for, it's to see if a user
has set a color. In a style class, I allow the user to set the NegNumber
color if he wants. I set the NegNumber Color to Color.Empty initially. In
the end class that uses the style class, I check to see if the NegNumber has
been set to a color by checking if the style class property is still empty
assuming if it's not, then the user has specified a negnumber color. I then
use either the overall forecolor for the control to display the number or, if
the negnumber is not still empty, I use that color.
 
J

Jay B. Harlow [MVP - Outlook]

Larry,
If color1.Name = color2.Name Then
Is not the same as Color.Equals. What happens when both colors are unnamed?
Your expression only supports named colors, Color.Equals supports named &
unnamed colors.
But you then end up with different syntax for the same type of operation.
Exactly my point!

Both of these:
If color1.Name = color2.Name Then

Are a different syntax!

In both of the above you compare an "attribute" of said object, you are not
comparing the objects themselves.

Where as Object.Equals is a standard convention in "modern" OO languages, as
evidenced by the fact it is an overridable method of System.Object the base
class of all objects.

As you (hopefully) know, the minimum you need to do to allow your type
(class or structure) to support comparisons is to override the Object.Equals
method. Then your Object will play nice with the Framework, such as
ArrayList.IndexOf & Array.IndexOf. For structures I override Object.Equals
as well as overload it for the structure itself. The overload avoids boxing
the value to compare to.

In other words all types (classes or structures) can use the Equals syntax,
not all types can use the = operator! Which means you can use the
v1.Equals(v2) syntax for booleans, bytes, singles, integers, longs, singles,
doubles, decimals, datetimes, chars, strings, colors, timespans, versions,
and every other type in the framework and all the types you define. If you
don't override it you get one behavior, if you do override then you get your
behavior!

In languages such as C# that support operator overloading, if the two
objects/values are comparable the Class or Structure normally has an
overloaded = operator that performs the comparison. In addition to
overriding Object.Equals. When you overload the = operator you are supposed
to also offer a Shared Compare method (such as TimeSpan.Compare), for some
reason Color does not. Also if you overload = you are suppose to overload
<>.

Unfortunately VB.NET tricks you in some cases, in that it offers its own
overload for the = operator when dealing with Strings, Decimals & DateTimes,
but neglects to use the overloaded operators for Color & TimeSpan & other
classes that have overloaded operators. Fortunately VB.NET 2005 fully
supports defining & using overloaded operators. I haven't checked if VB.NET
2005 continues to do its own thing for String, Decimal, & DateTime or if it
"correctly" calls the overloaded operator = for the classes.

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

Dennis,
Actually to check for Color.Empty specifically you can use the IsEmpty
property:

If mycolor.IsEmpty Then

To see what the various methods we've discussed may or may not return try
the following:

Dim c1 As Color = Color.Empty
Dim c2 As Color = Color.Black
Dim c3 As Color = Color.FromArgb(0, 0, 0, 0)

Debug.WriteLine(c1, "c1") ' same as c1.ToString()
Debug.WriteLine(c2, "c2")
Debug.WriteLine(c3, "c3")

Debug.WriteLine(c1.ToArgb().ToString("x4"), "c1.ToArgb")
Debug.WriteLine(c2.ToArgb().ToString("x4"), "c2.ToArgb")
Debug.WriteLine(c3.ToArgb().ToString("x4"), "c3.ToArgb")

Debug.WriteLine(c1.Name(), "c1.Name")
Debug.WriteLine(c2.Name(), "c2.Name")
Debug.WriteLine(c3.Name(), "c3.Name")

Debug.WriteLine(c1.ToKnownColor(), "c1.ToKnownColor")
Debug.WriteLine(c2.ToKnownColor(), "c2.ToKnownColor")
Debug.WriteLine(c3.ToKnownColor(), "c3.ToKnownColor")

Debug.WriteLine(c1.IsEmpty, "c1.IsEmpty")
Debug.WriteLine(c2.IsEmpty, "c2.IsEmpty")
Debug.WriteLine(c3.IsEmpty, "c3.IsEmpty")

Debug.WriteLine(c1.IsKnownColor, "c1.IsKnownColor")
Debug.WriteLine(c2.IsKnownColor, "c2.IsKnownColor")
Debug.WriteLine(c3.IsKnownColor, "c3.IsKnownColor")

Debug.WriteLine(c1.IsNamedColor, "c1.IsNamedColor")
Debug.WriteLine(c2.IsNamedColor, "c2.IsNamedColor")
Debug.WriteLine(c3.IsNamedColor, "c3.IsNamedColor")

Debug.WriteLine(c1.IsSystemColor, "c1.IsSystemColor")
Debug.WriteLine(c2.IsSystemColor, "c2.IsSystemColor")
Debug.WriteLine(c3.IsSystemColor, "c3.IsSystemColor")

Debug.WriteLine(c1.Equals(Color.Empty), "c1.equals")
Debug.WriteLine(c2.Equals(Color.Empty), "c2.equals")
Debug.WriteLine(c3.Equals(Color.Empty), "c3.equals")

I was half expecting Color.Empty to equal Color.FromArgb(0, 0, 0, 0),
however as the above shows it does not.

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

Oops!
These three should really use "x8" instead of "x4":
Debug.WriteLine(c1.ToArgb().ToString("x4"), "c1.ToArgb")
Debug.WriteLine(c2.ToArgb().ToString("x4"), "c2.ToArgb")
Debug.WriteLine(c3.ToArgb().ToString("x4"), "c3.ToArgb")

Jay
 
L

Larry Serflaten

Jay B. Harlow said:
Larry,
Is not the same as Color.Equals.

I find that it is the same.....
What happens when both colors are unnamed?

Name returns the RGB value, which can be compared.
Your expression only supports named colors, Color.Equals supports named &
unnamed colors.

Name supports named colors by returning their name, and it supports unnamed
colors by returning the Hex value of the color.

Exactly my point!

Not a good idea, in my book!


Both of these:


Are a different syntax!

I'd say they are closer to each other than having to pass in a parameter
as was done with the Equals function.
In both of the above you compare an "attribute" of said object, you are not
comparing the objects themselves.

Correct, but its the attribute of the object that is desired. They both return
values that can be compared. That is the way it should be done (and that is
the way it is implemented!) The color1.Equals(color2) method should be
reserved for object comparison, such as:

Dim color1 as Color = Color.White
Dim color2 as Color = color1

In that case, the Equals function should return True because both references
point to the same object. That is also why it returns True in your case, when
both references point to the same Color.Black object. The problem is that
a Color type is not an 'object', it is a structure, so the following is not valid:

If color1 Is color2 Then ...

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. But Is is not
allowed when comparing value types, however the Equals method is provided
when that type of comparison is needed. And, I would suggest, that is when
it should be used.

LFS
 
J

Jay B. Harlow [MVP - Outlook]

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top