Trier un IList en C #

J’ai donc rencontré un problème intéressant aujourd’hui. Nous avons un service Web WCF qui renvoie un IList. Pas vraiment un gros problème jusqu’à ce que je veuille le sortinger.

L’interface IList ne possède pas de méthode de sorting intégrée.

J’ai fini par utiliser la méthode ArrayList.Adapter(list).Sort(new MyComparer()) pour résoudre le problème, mais cela me semblait un peu “ghetto”.

J’ai joué avec l’écriture d’une méthode d’extension, avec l’inheritance d’IList et l’implémentation de ma propre méthode Sort () ainsi que la conversion à une liste, mais aucune d’entre elles ne semblait trop élégante.

Donc, ma question est, est-ce que quelqu’un a une solution élégante pour sortinger un IList

Que diriez-vous d’utiliser LINQ To Objects pour sortinger pour vous?

Disons que vous avez un IList , et que la voiture a une propriété Engine , je pense que vous pouvez sortinger comme suit:

 from c in list orderby c.Engine select c; 

Edit: Vous devez être rapide pour obtenir des réponses ici. Comme je présentais une syntaxe légèrement différente des autres réponses, je laisserai ma réponse – cependant, les autres réponses présentées sont également valables.

Vous pouvez utiliser LINQ:

 using System.Linq; IList list = new List(); IEnumerable sortedEnum = list.OrderBy(f=>f.Bar); IList sortedList = sortedEnum.ToList(); 

Cette question m’a incité à écrire un article de blog: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

Je pense que, idéalement, le .NET Framework inclurait une méthode de sorting statique qui accepte un IList , mais la meilleure solution consiste à créer votre propre méthode d’extension. Ce n’est pas trop difficile de créer quelques méthodes qui vous permettront de sortinger un IList comme vous le feriez avec List . En bonus, vous pouvez surcharger la méthode d’extension LINQ OrderBy en utilisant la même technique, de sorte que, que vous utilisiez List.Sort, IList.Sort ou IEnumerable.OrderBy, vous pouvez utiliser exactement la même syntaxe.

 public static class SortExtensions { // Sorts an IList in place. public static void Sort(this IList list, Comparison comparison) { ArrayList.Adapter((IList)list).Sort(new ComparisonComparer(comparison)); } // Convenience method on IEnumerable to allow passing of a // Comparison delegate to the OrderBy method. public static IEnumerable OrderBy(this IEnumerable list, Comparison comparison) { return list.OrderBy(t => t, new ComparisonComparer(comparison)); } } // Wraps a generic Comparison delegate in an IComparer to make it easy // to use a lambda expression for methods that take an IComparer or IComparer public class ComparisonComparer : IComparer, IComparer { private readonly Comparison _comparison; public ComparisonComparer(Comparison comparison) { _comparison = comparison; } public int Compare(T x, T y) { return _comparison(x, y); } public int Compare(object o1, object o2) { return _comparison((T)o1, (T)o2); } } 

Avec ces extensions, sortingez votre IList comme vous le feriez pour une liste:

 IList iList = new [] { "Carlton", "Alison", "Bob", "Eric", "David" }; // Use the custom extensions: // Sort in-place, by ssortingng length iList.Sort((s1, s2) => s1.Length.CompareTo(s2.Length)); // Or use OrderBy() IEnumerable ordered = iList.OrderBy((s1, s2) => s1.Length.CompareTo(s2.Length)); 

Il y a plus d’informations dans le post: http://blog.velir.com/index.php/2011/02/17/ilistt-sorting-a-better-way/

Vous allez devoir faire quelque chose comme ça, je pense (le convertir en un type plus concret).

Prenez-le peut-être dans une liste de T plutôt que dans ArrayList, de sorte que vous obtenez une sécurité de type et plus d’options pour la mise en œuvre du comparateur.

La réponse acceptée par @DavidMills est plutôt bonne, mais je pense que cela peut être amélioré. D’une part, il n’est pas nécessaire de définir la classe ComparisonComparer lorsque la structure inclut déjà une méthode statique Comparer.Create(Comparison) . Cette méthode peut être utilisée pour créer une IComparison à la volée.

En outre, il lance IList sur IList ce qui peut être dangereux. Dans la plupart des cas, List qui implémente IList est utilisé dans les coulisses pour implémenter IList , mais cela n’est pas garanti et peut conduire à un code fragile.

Enfin, la méthode List.Sort() surchargée comporte 4 signatures et seulement 2 d’entre elles sont implémentées.

  1. List.Sort()
  2. List.Sort(Comparison)
  3. List.Sort(IComparer)
  4. List.Sort(Int32, Int32, IComparer)

La classe ci-dessous implémente les 4 signatures List.Sort() pour l’interface IList :

 using System; using System.Collections.Generic; public static class IListExtensions { public static void Sort(this IList list) { if (list is List) { ((List)list).Sort(); } else { List copy = new List(list); copy.Sort(); Copy(copy, 0, list, 0, list.Count); } } public static void Sort(this IList list, Comparison comparison) { if (list is List) { ((List)list).Sort(comparison); } else { List copy = new List(list); copy.Sort(comparison); Copy(copy, 0, list, 0, list.Count); } } public static void Sort(this IList list, IComparer comparer) { if (list is List) { ((List)list).Sort(comparer); } else { List copy = new List(list); copy.Sort(comparer); Copy(copy, 0, list, 0, list.Count); } } public static void Sort(this IList list, int index, int count, IComparer comparer) { if (list is List) { ((List)list).Sort(index, count, comparer); } else { List range = new List(count); for (int i = 0; i < count; i++) { range.Add(list[index + i]); } range.Sort(comparer); Copy(range, 0, list, index, count); } } private static void Copy(IList sourceList, int sourceIndex, IList destinationList, int destinationIndex, int count) { for (int i = 0; i < count; i++) { destinationList[destinationIndex + i] = sourceList[sourceIndex + i]; } } } 

Usage:

 class Foo { public int Bar; public Foo(int bar) { this.Bar = bar; } } void TestSort() { IList ints = new List() { 1, 4, 5, 3, 2 }; IList foos = new List() { new Foo(1), new Foo(4), new Foo(5), new Foo(3), new Foo(2), }; ints.Sort(); foos.Sort((x, y) => Comparer.Default.Compare(x.Bar, y.Bar)); } 

L'idée ici est d'exploiter les fonctionnalités de la List sous-jacente List pour gérer le sorting chaque fois que cela est possible. Encore une fois, la plupart des implémentations IList que j'ai vues utilisent ceci. Dans le cas où la collection sous-jacente est d'un type différent, créez une nouvelle instance de List avec des éléments de la liste d'entrée, utilisez-la pour effectuer le sorting, puis copiez les résultats dans la liste d'entrée. Cela fonctionnera même si la liste d'entrée IList pas l'interface IList .

Convertissez votre IList en List ou en une autre collection générique, puis vous pourrez facilement l’interroger / le sortinger à l’aide de l’ System.Linq noms System.Linq (il fournira un tas de méthodes d’extension)

J’ai trouvé ce fil alors que je cherchais une solution au problème exact décrit dans le message original. Cependant, aucune des réponses ne répondait entièrement à ma situation. La réponse de Brody était assez proche. Voici ma situation et la solution que j’ai trouvée.

J’ai deux IList du même type retournés par NHibernate et j’ai émergé les deux IList en un seul, d’où le besoin de sortinger.

Comme Brody a dit que j’ai implémenté un ICompare sur l’object (ReportFormat) qui est le type de mon IList:

  public class FormatCcdeSorter:IComparer { public int Compare(ReportFormat x, ReportFormat y) { return x.FormatCode.CompareTo(y.FormatCode); } } 

Je convertis ensuite le fichier IList fusionné en un tableau du même type:

 ReportFormat[] myReports = new ReportFormat[reports.Count]; //reports is the merged IList 

Ensuite, sortingez le tableau:

 Array.Sort(myReports, new FormatCodeSorter());//sorting using custom comparer 

Comme le tableau unidimensionnel implémente l’interface System.Collections.Generic.IList , le tableau peut être utilisé comme l’IList d’origine.

Utile pour le sorting en grid cette méthode sortinge la liste en fonction des noms de propriété. Comme suit l’exemple.

  List temp = new List(); temp.Add(new MeuTeste(2, "ramster", DateTime.Now)); temp.Add(new MeuTeste(1, "ball", DateTime.Now)); temp.Add(new MeuTeste(8, "gimm", DateTime.Now)); temp.Add(new MeuTeste(3, "dies", DateTime.Now)); temp.Add(new MeuTeste(9, "random", DateTime.Now)); temp.Add(new MeuTeste(5, "call", DateTime.Now)); temp.Add(new MeuTeste(6, "simple", DateTime.Now)); temp.Add(new MeuTeste(7, "silver", DateTime.Now)); temp.Add(new MeuTeste(4, "inn", DateTime.Now)); SortList(ref temp, SortDirection.Ascending, "MyProperty"); private void SortList( ref List lista , SortDirection sort , ssortingng propertyToOrder) { if (!ssortingng.IsNullOrEmpty(propertyToOrder) && lista != null && lista.Count > 0) { Type t = lista[0].GetType(); if (sort == SortDirection.Ascending) { lista = lista.OrderBy( a => t.InvokeMember( propertyToOrder , System.Reflection.BindingFlags.GetProperty , null , a , null ) ).ToList(); } else { lista = lista.OrderByDescending( a => t.InvokeMember( propertyToOrder , System.Reflection.BindingFlags.GetProperty , null , a , null ) ).ToList(); } } } 

Voici un exemple utilisant le typage plus fort. Je ne sais pas si c’est nécessairement la meilleure façon.

 static void Main(ssortingng[] args) { IList list = new List() { 1, 3, 2, 5, 4, 6, 9, 8, 7 }; List stronglyTypedList = new List(Cast(list)); stronglyTypedList.Sort(); } private static IEnumerable Cast(IEnumerable list) { foreach (T item in list) { yield return item; } } 

La fonction Cast est juste une réimplémentation de la méthode d’extension fournie avec la méthode 3.5 écrite en tant que méthode statique normale. C’est assez laid et verbeux malheureusement.

Dans VS2008, lorsque je clique sur la référence de service et que vous sélectionnez “Configurer une référence de service”, vous avez la possibilité de choisir la manière dont le client désérialise les listes renvoyées par le service.

Je peux notamment choisir entre System.Array, System.Collections.ArrayList et System.Collections.Generic.List

 using System.Linq; var yourList = SomeDAO.GetRandomThings(); yourList.ToList().Sort( (thing, randomThing) => thing.CompareThisProperty.CompareTo( randomThing.CompareThisProperty ) ); 

C’est joli! Ghetto.

J’ai trouvé un bon message à ce sujet et j’ai pensé partager. Vérifiez le ici

Fondamentalement.

Vous pouvez créer la classe et les classes IComparer suivantes

 public class Widget { public ssortingng Name = ssortingng.Empty; public int Size = 0; public Widget(ssortingng name, int size) { this.Name = name; this.Size = size; } } public class WidgetNameSorter : IComparer { public int Compare(Widget x, Widget y) { return x.Name.CompareTo(y.Name); } } public class WidgetSizeSorter : IComparer { public int Compare(Widget x, Widget y) { return x.Size.CompareTo(y.Size); } } 

Ensuite, si vous avez un IList, vous pouvez le sortinger comme ceci.

 List widgets = new List(); widgets.Add(new Widget("Zeta", 6)); widgets.Add(new Widget("Beta", 3)); widgets.Add(new Widget("Alpha", 9)); widgets.Sort(new WidgetNameSorter()); widgets.Sort(new WidgetSizeSorter()); 

Mais consultez ce site pour plus d’informations … Check it out ICI

Est-ce une solution valide?

  IList ilist = new List(); ilist.Add("B"); ilist.Add("A"); ilist.Add("C"); Console.WriteLine("IList"); foreach (ssortingng val in ilist) Console.WriteLine(val); Console.WriteLine(); List list = (List)ilist; list.Sort(); Console.WriteLine("List"); foreach (ssortingng val in list) Console.WriteLine(val); Console.WriteLine(); list = null; Console.WriteLine("IList again"); foreach (ssortingng val in ilist) Console.WriteLine(val); Console.WriteLine(); 

Le résultat était: IList B A C

Liste A B C

IList encore A B C

 try this **USE ORDER BY** : public class Employee { public ssortingng Id { get; set; } public ssortingng Name { get; set; } } private static IList GetItems() { List lst = new List(); lst.Add(new Employee { Id = "1", Name = "Emp1" }); lst.Add(new Employee { Id = "2", Name = "Emp2" }); lst.Add(new Employee { Id = "7", Name = "Emp7" }); lst.Add(new Employee { Id = "4", Name = "Emp4" }); lst.Add(new Employee { Id = "5", Name = "Emp5" }); lst.Add(new Employee { Id = "6", Name = "Emp6" }); lst.Add(new Employee { Id = "3", Name = "Emp3" }); return lst; } **var lst = GetItems().AsEnumerable(); var orderedLst = lst.OrderBy(t => t.Id).ToList(); orderedLst.ForEach(emp => Console.WriteLine("Id - {0} Name -{1}", emp.Id, emp.Name));**