List.Sort( IComparer )… a casa mia si chiama(va) bug…
Preambolo. Avete una classe del tipo:
ne avete n istanze in una lista e volete ordinare la lista in base al valore della proprietà Value, per farlo è necessario utilizzare un IComparerclass Tupla { public Int32 Value { get; set; } public String Description { get; set; } }
peccaco che succedano un po’ di cose curiose :-D, questo test fallisce miseramente:class TuplaComparer : IComparer<Tupla> { public int Compare( Tupla x, Tupla y ) { return x.Value.CompareTo( y.Value ); } }
il metodo Sort() cioè swappa gli elementi uguali, ma secondo me non è il comportamento corretto, se sono uguali, e lo dice il vostro IComparer[TestMethod] public void tuplaComparer_using_listOfT_sort_should_sort_as_expected() { var list = new List<Tupla>() { new Tupla() { Value = 0, Description = "B" }, new Tupla() { Value = 0, Description = "A" } }; list.Sort( new TuplaComparer() ); Assert.AreEqual<String>( "B", list[ 0 ].Description ); Assert.AreEqual<String>( "A", list[ 1 ].Description ); }
Utilizzando infatti un altro meccanismo di sort il comportamento è quello atteso:
In questo caso, utilizzando lo stesso IComparer[TestMethod] public void tuplaComparer_using_linq_sort_should_sort_as_expected() { var list = new List<Tupla>() { new Tupla() { Value = 0, Description = "B" }, new Tupla() { Value = 0, Description = "A" } }; var actual = list.OrderBy( t => t, new TuplaComparer() ); Assert.AreEqual<String>( "B", actual.ElementAt( 0 ).Description ); Assert.AreEqual<String>( "A", actual.ElementAt( 1 ).Description ); }
A casa mia si chiama
Update:
Non è un bug ma un comportamento documentato: http://msdn.microsoft.com/en-us/library/234b841s.aspx.m
Si chiama “Unstable Sort” e non garantisce l’ordine degli elementi in caso di uguaglianza, esattamente il mio caso, mentre la OrderBy() invece implementa uno “Stable Sort” garantendo l’ordine degli elementi in caso di uguaglianza.
Grazie a Luka per la segnalazione.