VB 2005 Express Collection(of T) IComparator

  • Thread starter Thread starter Michael D. Ober
  • Start date Start date
M

Michael D. Ober

In the code below, the IComparator function is never called. What am I
missing?

Public Class ArchiveInfo
Implements System.IComparable(Of ArchiveInfo)

Public FullName As String = ""
Public AccountNumber As String = ""

Public Sub New(ByRef Account As String, ByVal fname As String)
AccountNumber = Trim$(Account)
FullName = Trim$(fname)
End Sub

Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
Implements System.IComparable(Of ArchiveInfo).CompareTo
Dim aiPath As String
Dim mePath As String
Dim i As Integer

i = InStr(other.FullName, "\archives\")
If i = 0 Then aiPath = other.FullName Else aiPath =
Mid$(other.FullName, i + Len("\archives\") + 1)

i = InStr(FullName, "\archives\")
If i = 0 Then mePath = FullName Else mePath = Mid$(FullName, i +
Len("\archives\") + 1)

Return aiPath.CompareTo(mePath)
End Function
End Class

Calling code:

dim Results as new Collection(of ArchiveInfo)

....

dim ai as new ArchiveInfo(someaccount, filename)
if not results.contains(ai) then results.add(ai)


===============
I understand that if results.count = 0 then the call shouldn't be made.
However, a breakpoint on the ArchiveInfo.CompareTo function is never
triggered.
 
When do you expect it to be called? The generic VB Collection(Of T)
class does not appear to be a sorted collection, therefore there is no
reason for your CompareTo method to be called. Have you tried using a
SortedList or just tried sorting the collection?
 
If you look at my code, you'll see that I'm trying to use the contains
method. Not sort the files.

Mike.
 
Michael,
Ah! There's the rub.

The documentation is wrong!

http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx

It states that Collection(Of T).Contains calls IComparable. As Chris states
IComparable is used for "ordered" lists.

I would expect Contains to call "Equals", as "Equals" is used for identity,
which in fact it does.

Change your class to implement IEquatable(Of T) and it will behave as you
expect.

| Public Class ArchiveInfo
| Implements System.IEquatable(Of ArchiveInfo)

I have not tried it I would expect the function to fall back to
Object.Equals if it does not implement IEquatable(Of T).

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| In the code below, the IComparator function is never called. What am I
| missing?
|
| Public Class ArchiveInfo
| Implements System.IComparable(Of ArchiveInfo)
|
| Public FullName As String = ""
| Public AccountNumber As String = ""
|
| Public Sub New(ByRef Account As String, ByVal fname As String)
| AccountNumber = Trim$(Account)
| FullName = Trim$(fname)
| End Sub
|
| Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
| Implements System.IComparable(Of ArchiveInfo).CompareTo
| Dim aiPath As String
| Dim mePath As String
| Dim i As Integer
|
| i = InStr(other.FullName, "\archives\")
| If i = 0 Then aiPath = other.FullName Else aiPath =
| Mid$(other.FullName, i + Len("\archives\") + 1)
|
| i = InStr(FullName, "\archives\")
| If i = 0 Then mePath = FullName Else mePath = Mid$(FullName, i +
| Len("\archives\") + 1)
|
| Return aiPath.CompareTo(mePath)
| End Function
| End Class
|
| Calling code:
|
| dim Results as new Collection(of ArchiveInfo)
|
| ...
|
| dim ai as new ArchiveInfo(someaccount, filename)
| if not results.contains(ai) then results.add(ai)
|
|
| ===============
| I understand that if results.count = 0 then the call shouldn't be made.
| However, a breakpoint on the ArchiveInfo.CompareTo function is never
| triggered.
|
|
|
 
Interesting. the Collection.Contains method could be implemented using
IComparable since if the values are equal, IComparable returns 0. This is
what makes this particular documentation bug rather insideous.
IEquatable(Of T) works.

Thanks,
Mike.

Michael D. Ober said:
Thanks. How do we report a documentation error?

Mike.

Jay B. Harlow said:
Michael,
Ah! There's the rub.

The documentation is wrong!

http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx

It states that Collection(Of T).Contains calls IComparable. As Chris states
IComparable is used for "ordered" lists.

I would expect Contains to call "Equals", as "Equals" is used for identity,
which in fact it does.

Change your class to implement IEquatable(Of T) and it will behave as you
expect.

| Public Class ArchiveInfo
| Implements System.IEquatable(Of ArchiveInfo)

I have not tried it I would expect the function to fall back to
Object.Equals if it does not implement IEquatable(Of T).

--
Hope this helps
Jay [MVP - Outlook]
.NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| In the code below, the IComparator function is never called. What am I
| missing?
|
| Public Class ArchiveInfo
| Implements System.IComparable(Of ArchiveInfo)
|
| Public FullName As String = ""
| Public AccountNumber As String = ""
|
| Public Sub New(ByRef Account As String, ByVal fname As String)
| AccountNumber = Trim$(Account)
| FullName = Trim$(fname)
| End Sub
|
| Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
| Implements System.IComparable(Of ArchiveInfo).CompareTo
| Dim aiPath As String
| Dim mePath As String
| Dim i As Integer
|
| i = InStr(other.FullName, "\archives\")
| If i = 0 Then aiPath = other.FullName Else aiPath =
| Mid$(other.FullName, i + Len("\archives\") + 1)
|
| i = InStr(FullName, "\archives\")
| If i = 0 Then mePath = FullName Else mePath = Mid$(FullName, i +
| Len("\archives\") + 1)
|
| Return aiPath.CompareTo(mePath)
| End Function
| End Class
|
| Calling code:
|
| dim Results as new Collection(of ArchiveInfo)
|
| ...
|
| dim ai as new ArchiveInfo(someaccount, filename)
| if not results.contains(ai) then results.add(ai)
|
|
| ===============
| I understand that if results.count = 0 then the call shouldn't be made.
| However, a breakpoint on the ArchiveInfo.CompareTo function is never
| triggered.
|
|
|
 
Mike,
I believe they are still accepting bug/feature requests at:

http://lab.msdn.microsoft.com/ProductFeedback/


--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|
| Thanks. How do we report a documentation error?
|
| Mike.
|
| message | >
| > Michael,
| > Ah! There's the rub.
| >
| > The documentation is wrong!
| >
| > http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx
| >
| > It states that Collection(Of T).Contains calls IComparable. As Chris
| states
| > IComparable is used for "ordered" lists.
| >
| > I would expect Contains to call "Equals", as "Equals" is used for
| identity,
| > which in fact it does.
| >
| > Change your class to implement IEquatable(Of T) and it will behave as
you
| > expect.
| >
| > | Public Class ArchiveInfo
| > | Implements System.IEquatable(Of ArchiveInfo)
| >
| > I have not tried it I would expect the function to fall back to
| > Object.Equals if it does not implement IEquatable(Of T).
| >
| > --
| > Hope this helps
| > Jay [MVP - Outlook]
| > .NET Application Architect, Enthusiast, & Evangelist
| > T.S. Bradley - http://www.tsbradley.net
| >
| >
| > | > | In the code below, the IComparator function is never called. What am
I
| > | missing?
| > |
| > | Public Class ArchiveInfo
| > | Implements System.IComparable(Of ArchiveInfo)
| > |
| > | Public FullName As String = ""
| > | Public AccountNumber As String = ""
| > |
| > | Public Sub New(ByRef Account As String, ByVal fname As String)
| > | AccountNumber = Trim$(Account)
| > | FullName = Trim$(fname)
| > | End Sub
| > |
| > | Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
| > | Implements System.IComparable(Of ArchiveInfo).CompareTo
| > | Dim aiPath As String
| > | Dim mePath As String
| > | Dim i As Integer
| > |
| > | i = InStr(other.FullName, "\archives\")
| > | If i = 0 Then aiPath = other.FullName Else aiPath =
| > | Mid$(other.FullName, i + Len("\archives\") + 1)
| > |
| > | i = InStr(FullName, "\archives\")
| > | If i = 0 Then mePath = FullName Else mePath = Mid$(FullName, i
+
| > | Len("\archives\") + 1)
| > |
| > | Return aiPath.CompareTo(mePath)
| > | End Function
| > | End Class
| > |
| > | Calling code:
| > |
| > | dim Results as new Collection(of ArchiveInfo)
| > |
| > | ...
| > |
| > | dim ai as new ArchiveInfo(someaccount, filename)
| > | if not results.contains(ai) then results.add(ai)
| > |
| > |
| > | ===============
| > | I understand that if results.count = 0 then the call shouldn't be
made.
| > | However, a breakpoint on the ArchiveInfo.CompareTo function is never
| > | triggered.
| > |
| > |
| > |
| >
| >
| >
|
|
|
 
Mike,
Yes it could however I would argue that it shouldn't as:

IEquatable is used "for determining equality of instances"
http://msdn2.microsoft.com/ms131187(en-US,VS.80).aspx


IComparable is used "a type-specific comparison method for ordering
instances"
http://msdn2.microsoft.com/4d7sx9hd(en-US,VS.80).aspx


Yes IEquatable & IComparable are closely related, however you can easily
have Equatable types without them being Comparable (GUID for example),
however you would rarely if ever have a Comparable type that is not
Equatable. In other words Comparable types should also be Equatable (), for
the reason you state. Compare = 0 indicates they are equal. NOTE: This is
not to say that a Type is defined such that no two instances would ever be
equal.


Contains is used to "determine whether an element is in the Collection".
http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx

Within the framework Contains is rather consistent in that it determines
whether the "element" is within that "collection", I have yet to find a
Contains that doesn't use Equality (Equatable) in its implementation,
whether its overloading Object.Equals or implementing IEquatable.

Some useful articles on IComparable & IEquatable:
http://blogs.msdn.com/kcwalina/archive/2004/10/27/248847.aspx

http://engineering.meta-comm.com/bl...uid,84ef2894-3bdc-44c3-91fb-e2e62179717a.aspx

Especially section 8.5 from the following book:
http://www.awprofessional.com/articles/article.asp?p=423349&seqNum=7&rl=1
Unfortunately I don't see the online version of the above book...


--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Interesting. the Collection.Contains method could be implemented using
| IComparable since if the values are equal, IComparable returns 0. This is
| what makes this particular documentation bug rather insideous.
| IEquatable(Of T) works.
|
| Thanks,
| Mike.
|
| | >
| > Thanks. How do we report a documentation error?
| >
| > Mike.
| >
| > message | > >
| > > Michael,
| > > Ah! There's the rub.
| > >
| > > The documentation is wrong!
| > >
| > > http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx
| > >
| > > It states that Collection(Of T).Contains calls IComparable. As Chris
| > states
| > > IComparable is used for "ordered" lists.
| > >
| > > I would expect Contains to call "Equals", as "Equals" is used for
| > identity,
| > > which in fact it does.
| > >
| > > Change your class to implement IEquatable(Of T) and it will behave as
| you
| > > expect.
| > >
| > > | Public Class ArchiveInfo
| > > | Implements System.IEquatable(Of ArchiveInfo)
| > >
| > > I have not tried it I would expect the function to fall back to
| > > Object.Equals if it does not implement IEquatable(Of T).
| > >
| > > --
| > > Hope this helps
| > > Jay [MVP - Outlook]
| > > .NET Application Architect, Enthusiast, & Evangelist
| > > T.S. Bradley - http://www.tsbradley.net
| > >
| > >
| > > | > > | In the code below, the IComparator function is never called. What
am
| I
| > > | missing?
| > > |
| > > | Public Class ArchiveInfo
| > > | Implements System.IComparable(Of ArchiveInfo)
| > > |
| > > | Public FullName As String = ""
| > > | Public AccountNumber As String = ""
| > > |
| > > | Public Sub New(ByRef Account As String, ByVal fname As String)
| > > | AccountNumber = Trim$(Account)
| > > | FullName = Trim$(fname)
| > > | End Sub
| > > |
| > > | Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
| > > | Implements System.IComparable(Of ArchiveInfo).CompareTo
| > > | Dim aiPath As String
| > > | Dim mePath As String
| > > | Dim i As Integer
| > > |
| > > | i = InStr(other.FullName, "\archives\")
| > > | If i = 0 Then aiPath = other.FullName Else aiPath =
| > > | Mid$(other.FullName, i + Len("\archives\") + 1)
| > > |
| > > | i = InStr(FullName, "\archives\")
| > > | If i = 0 Then mePath = FullName Else mePath = Mid$(FullName,
i
| +
| > > | Len("\archives\") + 1)
| > > |
| > > | Return aiPath.CompareTo(mePath)
| > > | End Function
| > > | End Class
| > > |
| > > | Calling code:
| > > |
| > > | dim Results as new Collection(of ArchiveInfo)
| > > |
| > > | ...
| > > |
| > > | dim ai as new ArchiveInfo(someaccount, filename)
| > > | if not results.contains(ai) then results.add(ai)
| > > |
| > > |
| > > | ===============
| > > | I understand that if results.count = 0 then the call shouldn't be
| made.
| > > | However, a breakpoint on the ArchiveInfo.CompareTo function is never
| > > | triggered.
| > > |
| > > |
| > > |
| > >
| > >
| > >
| >
| >
| >
| >
|
|
|
 
Jay,

I agree with you. I was just pointing out that since IComparable can be
used for IEquatable, the incorrect documentation is extremely misleading. I
probably wouldn't have gotten to IEquatable without the assistance here. I
have used IComparable for sorted lists and collections, so I understand how
it's used for that purpose.

Mike.

Jay B. Harlow said:
Mike,
Yes it could however I would argue that it shouldn't as:

IEquatable is used "for determining equality of instances"
http://msdn2.microsoft.com/ms131187(en-US,VS.80).aspx


IComparable is used "a type-specific comparison method for ordering
instances"
http://msdn2.microsoft.com/4d7sx9hd(en-US,VS.80).aspx


Yes IEquatable & IComparable are closely related, however you can easily
have Equatable types without them being Comparable (GUID for example),
however you would rarely if ever have a Comparable type that is not
Equatable. In other words Comparable types should also be Equatable (), for
the reason you state. Compare = 0 indicates they are equal. NOTE: This is
not to say that a Type is defined such that no two instances would ever be
equal.


Contains is used to "determine whether an element is in the Collection".
http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx

Within the framework Contains is rather consistent in that it determines
whether the "element" is within that "collection", I have yet to find a
Contains that doesn't use Equality (Equatable) in its implementation,
whether its overloading Object.Equals or implementing IEquatable.

Some useful articles on IComparable & IEquatable:
http://blogs.msdn.com/kcwalina/archive/2004/10/27/248847.aspx

http://engineering.meta-comm.com/bl...uid,84ef2894-3bdc-44c3-91fb-e2e62179717a.aspx

Especially section 8.5 from the following book:
http://www.awprofessional.com/articles/article.asp?p=423349&seqNum=7&rl=1
Unfortunately I don't see the online version of the above book...


--
Hope this helps
Jay [MVP - Outlook]
.NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Interesting. the Collection.Contains method could be implemented using
| IComparable since if the values are equal, IComparable returns 0. This is
| what makes this particular documentation bug rather insideous.
| IEquatable(Of T) works.
|
| Thanks,
| Mike.
|
| | >
| > Thanks. How do we report a documentation error?
| >
| > Mike.
| >
| > message | > >
| > > Michael,
| > > Ah! There's the rub.
| > >
| > > The documentation is wrong!
| > >
| > > http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx
| > >
| > > It states that Collection(Of T).Contains calls IComparable. As Chris
| > states
| > > IComparable is used for "ordered" lists.
| > >
| > > I would expect Contains to call "Equals", as "Equals" is used for
| > identity,
| > > which in fact it does.
| > >
| > > Change your class to implement IEquatable(Of T) and it will behave as
| you
| > > expect.
| > >
| > > | Public Class ArchiveInfo
| > > | Implements System.IEquatable(Of ArchiveInfo)
| > >
| > > I have not tried it I would expect the function to fall back to
| > > Object.Equals if it does not implement IEquatable(Of T).
| > >
| > > --
| > > Hope this helps
| > > Jay [MVP - Outlook]
| > > .NET Application Architect, Enthusiast, & Evangelist
| > > T.S. Bradley - http://www.tsbradley.net
| > >
| > >
| > > | > > | In the code below, the IComparator function is never called. What
am
| I
| > > | missing?
| > > |
| > > | Public Class ArchiveInfo
| > > | Implements System.IComparable(Of ArchiveInfo)
| > > |
| > > | Public FullName As String = ""
| > > | Public AccountNumber As String = ""
| > > |
| > > | Public Sub New(ByRef Account As String, ByVal fname As String)
| > > | AccountNumber = Trim$(Account)
| > > | FullName = Trim$(fname)
| > > | End Sub
| > > |
| > > | Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
| > > | Implements System.IComparable(Of ArchiveInfo).CompareTo
| > > | Dim aiPath As String
| > > | Dim mePath As String
| > > | Dim i As Integer
| > > |
| > > | i = InStr(other.FullName, "\archives\")
| > > | If i = 0 Then aiPath = other.FullName Else aiPath =
| > > | Mid$(other.FullName, i + Len("\archives\") + 1)
| > > |
| > > | i = InStr(FullName, "\archives\")
| > > | If i = 0 Then mePath = FullName Else mePath = Mid$(FullName,
i
| +
| > > | Len("\archives\") + 1)
| > > |
| > > | Return aiPath.CompareTo(mePath)
| > > | End Function
| > > | End Class
| > > |
| > > | Calling code:
| > > |
| > > | dim Results as new Collection(of ArchiveInfo)
| > > |
| > > | ...
| > > |
| > > | dim ai as new ArchiveInfo(someaccount, filename)
| > > | if not results.contains(ai) then results.add(ai)
| > > |
| > > |
| > > | ===============
| > > | I understand that if results.count = 0 then the call shouldn't be
| made.
| > > | However, a breakpoint on the ArchiveInfo.CompareTo function is never
| > > | triggered.
| > > |
| > > |
| > > |
| > >
| > >
| > >
| >
| >
| >
| >
|
|
|
 
Reported.

Mike.

Jay B. Harlow said:
Mike,
I believe they are still accepting bug/feature requests at:

http://lab.msdn.microsoft.com/ProductFeedback/


--
Hope this helps
Jay [MVP - Outlook]
.NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|
| Thanks. How do we report a documentation error?
|
| Mike.
|
| message | >
| > Michael,
| > Ah! There's the rub.
| >
| > The documentation is wrong!
| >
| > http://msdn2.microsoft.com/ms132407(en-US,VS.80).aspx
| >
| > It states that Collection(Of T).Contains calls IComparable. As Chris
| states
| > IComparable is used for "ordered" lists.
| >
| > I would expect Contains to call "Equals", as "Equals" is used for
| identity,
| > which in fact it does.
| >
| > Change your class to implement IEquatable(Of T) and it will behave as
you
| > expect.
| >
| > | Public Class ArchiveInfo
| > | Implements System.IEquatable(Of ArchiveInfo)
| >
| > I have not tried it I would expect the function to fall back to
| > Object.Equals if it does not implement IEquatable(Of T).
| >
| > --
| > Hope this helps
| > Jay [MVP - Outlook]
| > .NET Application Architect, Enthusiast, & Evangelist
| > T.S. Bradley - http://www.tsbradley.net
| >
| >
| > | > | In the code below, the IComparator function is never called. What am
I
| > | missing?
| > |
| > | Public Class ArchiveInfo
| > | Implements System.IComparable(Of ArchiveInfo)
| > |
| > | Public FullName As String = ""
| > | Public AccountNumber As String = ""
| > |
| > | Public Sub New(ByRef Account As String, ByVal fname As String)
| > | AccountNumber = Trim$(Account)
| > | FullName = Trim$(fname)
| > | End Sub
| > |
| > | Public Function CompareTo(ByVal other As ArchiveInfo) As Integer
| > | Implements System.IComparable(Of ArchiveInfo).CompareTo
| > | Dim aiPath As String
| > | Dim mePath As String
| > | Dim i As Integer
| > |
| > | i = InStr(other.FullName, "\archives\")
| > | If i = 0 Then aiPath = other.FullName Else aiPath =
| > | Mid$(other.FullName, i + Len("\archives\") + 1)
| > |
| > | i = InStr(FullName, "\archives\")
| > | If i = 0 Then mePath = FullName Else mePath = Mid$(FullName, i
+
| > | Len("\archives\") + 1)
| > |
| > | Return aiPath.CompareTo(mePath)
| > | End Function
| > | End Class
| > |
| > | Calling code:
| > |
| > | dim Results as new Collection(of ArchiveInfo)
| > |
| > | ...
| > |
| > | dim ai as new ArchiveInfo(someaccount, filename)
| > | if not results.contains(ai) then results.add(ai)
| > |
| > |
| > | ===============
| > | I understand that if results.count = 0 then the call shouldn't be
made.
| > | However, a breakpoint on the ArchiveInfo.CompareTo function is never
| > | triggered.
| > |
| > |
| > |
| >
| >
| >
|
|
|
 
Back
Top