Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / June 2006

Tip: Looking for answers? Try searching our database.

IComparer (or the IComparable methods it relies upon) did not retu

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Darragh Jones - 23 Jun 2006 16:55 GMT
I'm trying to figure out why I'm getting the following error message when
trying to radomly sort a list of custom objects. In particular I've noticed
the following strange behaviour I'm hoping someone could shed some light
on....

1. When the list contains only 3 objects the sort works fine, unless I
remove the 'if x.equals(y)' check in the compare function.

2. When there are more than 3 objects I get the error even when this check
is in place (albeit it usually takes a bit longer).

------------------------ERROR MESSAGE----------------------------
IComparer (or the IComparable methods it relies upon) did not return zero
when Array.Sort called x. CompareTo(x)

-------------------------CODE LISTING--------------------------------

Module Module1

   Sub Main()
       Dim People As New System.Collections.Generic.List(Of Person)
       Dim Counter As Integer = 0
       People.Add(New Person(1, "Brian"))
       People.Add(New Person(2, "Darragh"))
       People.Add(New Person(3, "Aoife"))
       People.Add(New Person(4, "Aidan")) ' when only 3 people I don't seem
to have a problem unless I remove the if x.Equals(y) check below!
       While True
           Counter += 1
           Console.WriteLine("Comparison {0}", Counter)
           People.Sort(New Person.Random())
       End While
   End Sub
End Module

Public Class Person
   Public ID As Integer
   Public Name As String

   Public Sub New(ByVal ID As Integer, ByVal Name As String)
       Me.ID = ID
       Me.Name = Name
   End Sub

   Public Overrides Function ToString() As String
       Return String.Format("ID={0}, Name={1}", Me.ID, Me.Name)
   End Function

   Class Random
       Implements System.Collections.Generic.IComparer(Of Person)

       Private Shared r As New System.Random

       Public Function Compare(ByVal x As Person, ByVal y As Person) As
Integer Implements System.Collections.Generic.IComparer(Of Person).Compare
           Console.Write("Comparing: x=[{0}], y=[{1}]", x, y)
           If x.Equals(y) Then Compare = 0 Else Compare = r.Next(-1, 2)
'removing this gives error when only 3 items
           'Compare = r.Next(-1, 2)
           Console.WriteLine("{0}Returning: {1}", vbTab, Compare)
       End Function

   End Class

End Class
sloan - 23 Jun 2006 17:50 GMT
I tried your code... in C#.  (I'm working with IComparers this week, so I
thought Id give your randomizer a run thru)

Here is mine:

int compareValue  = 0;
if (x.Equals(y))

{

compareValue = 0;

}

else

{

compareValue = m_random.Next(-1, 2);

}

//'removing this gives error when only 3 items

compareValue = m_random.Next(-1, 2);

return compareValue;

and I have a member variable:
private System.Random m_random = new System.Random();

First, you may want to put

Option Strict On
Option Explicit On

at the top of your vb code.

Private Shared r As New System.Random

needs to be rewritten as:

Private Shared r System.Random = New System.Random()

So I think its either that. or the static/shared thing you are doing.

I did not experience the issue with 2 or 3 items in my collection.

> I'm trying to figure out why I'm getting the following error message when
> trying to radomly sort a list of custom objects. In particular I've noticed
[quoted text clipped - 61 lines]
>
> End Class
sloan - 23 Jun 2006 18:07 GMT
Actually, now I see what you're talking about.

I had to run it 3 times before I got the error.  But I did get it.

One thing is that one of my objects (x or y) is null/Nothing for some
unknown reason.

Hmmm..  I'll still looking at this sucker.

> I'm trying to figure out why I'm getting the following error message when
> trying to radomly sort a list of custom objects. In particular I've noticed
[quoted text clipped - 61 lines]
>
> End Class
sloan - 23 Jun 2006 19:27 GMT
http://msmvps.com/blogs/jon.skeet/archive/2005/12/02/77520.aspx

I think it has something to do with thread safety.

I've even tried a more anal RandomNumber getter:

I don't have an answer.  As soon as you take out the Random.Next... it
doesn't blow up.

Please post a solution here if you figure it out.

class RandomNumberGetter

{

private System.Random m_random = null;//new System.Random();

//private static readonly object padlock = new object();

//private readonly object padlock = new object();

private object padlock = new object();

public RandomNumberGetter()

{

lock (padlock)

{

this.m_random = new Random();

}

}

public int GetRandomNumber(int x, int y)

{

lock (padlock)

{

return this.m_random.Next(x, y);

}

}

}

> I'm trying to figure out why I'm getting the following error message when
> trying to radomly sort a list of custom objects. In particular I've noticed
[quoted text clipped - 61 lines]
>
> End Class
Jon Skeet [C# MVP] - 24 Jun 2006 00:51 GMT
<=?Utf-8?B?RGFycmFnaCBKb25lcw==?= <Darragh
Jones@discussions.microsoft.com>> wrote:
> I'm trying to figure out why I'm getting the following error message when
> trying to radomly sort a list of custom objects.

I suspect the problem is in the exception message. Basically, by
implementing IComparer randomly, you're breaking the contract by not
making it reflexive. You're saying that at the samt time, x > y and
y > x can both be true. That makes it impossible to sort.

What's your actual aim here? If you want to shuffle the list, there are
much better ways of doing it.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Darragh Jones - 26 Jun 2006 11:24 GMT
Thanks Jon for your help. I see now what I was doing wrong. Using Sort to
randomize the list was probably not the cleverest thing I've ever done.

I've decided to take a more straight forward approach...

Private Function Randomize(ByVal list As Collections.Generic.List(Of
Person)) As Collections.Generic.List(Of Person)
       Randomize = New Collections.Generic.List(Of Person)
       Dim index As Integer
       Dim r As New Random()
       While list.Count > 0
           index = r.Next(list.Count)
           Randomize.Add(list.Item(index))
           list.RemoveAt(index)
       End While
   End Function

>  <=?Utf-8?B?RGFycmFnaCBKb25lcw==?= <Darragh
> Jones@discussions.microsoft.com>> wrote:
[quoted text clipped - 8 lines]
> What's your actual aim here? If you want to shuffle the list, there are
> much better ways of doing it.
Jon Skeet [C# MVP] - 26 Jun 2006 20:37 GMT
> Thanks Jon for your help. I see now what I was doing wrong. Using Sort to
> randomize the list was probably not the cleverest thing I've ever done.
[quoted text clipped - 12 lines]
>         End While
>     End Function

While that will do it, it's not a terribly nice way of doing it, as it
involves creating a new list unnecessarily. There's a really neat
technique which shuffles a list. Imagine that the list has a dividing
line between unshuffled values and shuffled values. Everything starts
unshuffled. You randomly pick one of the unshuffled values and swap it
with the first unshuffled value, then move the imaginary line to past
that element. Keep going until everything is shuffled.

It's O(n) and very simple to implement. Unfortunately I don't have time
to do it for you in VB.NET right now, but here's an implementation in
C#:

   static readonly Random rng = new Random();
   public static void Shuffle (IList list)
   {
       // Note: last element doesn't need shuffling! (Couldn't
       // pick a different one to itself anyway.)
       for (int i=0; i < list.Count-1; i++)
       {
           object x = list[i];

           int index = rng.Next(list.Count-i)+i;
           list[i]=list[index];
           list[index]=x;
       }
   }

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Jon Skeet [C# MVP] - 24 Jun 2006 00:51 GMT
<=?Utf-8?B?RGFycmFnaCBKb25lcw==?= <Darragh
Jones@discussions.microsoft.com>> wrote:
> I'm trying to figure out why I'm getting the following error message when
> trying to radomly sort a list of custom objects. In particular I've noticed
> the following strange behaviour I'm hoping someone could shed some light
> on....

<snip>

Here's a short but complete program which demonstrates the problem with
no randomness:

using System;
using System.Collections.Generic;

class Test
{
   static void Main()
   {
       List<string> list = new List<string>();
       list.Add("a");
       list.Add("b");
       list.Add("c");
       list.Add("d");
       
       list.Sort(new DodgyComparer<string>());
   }
}

class DodgyComparer<T> : IComparer<T>
{
   int[] results = {-1, 0, 1, -1, 0, -1, -1, -1, 100};
   int index=0;
   
   public int Compare(T x, T y)
   {
       Console.WriteLine (x+" "+y+" "+results[index]);
       return results[index++];
   }
}

(The 100 is there to show that it's not going off the end of the array.
As a side issue, the same exception is thrown if the comparer throws
IndexOutOfRangeException, which made this awkward to diagnose.)

I've reported it to MS:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?
FeedbackID=145253

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.