Sorting an IList in C#

前端 未结 15 2242
臣服心动
臣服心动 2020-11-28 06:36

So I came across an interesting problem today. We have a WCF web service that returns an IList. Not really a big deal until I wanted to sort it.

Turns out the IList

相关标签:
15条回答
  • 2020-11-28 06:47

    You can use LINQ:

    using System.Linq;
    
    IList<Foo> list = new List<Foo>();
    IEnumerable<Foo> sortedEnum = list.OrderBy(f=>f.Bar);
    IList<Foo> sortedList = sortedEnum.ToList();
    
    0 讨论(0)
  • 2020-11-28 06:49

    Useful for grid sorting this method sorts list based on property names. As follow the example.

        List<MeuTeste> temp = new List<MeuTeste>();
    
        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<T>(
        ref List<T> lista
        , SortDirection sort
        , string propertyToOrder)
        {
            if (!string.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();
                }
            }
        }
    
    0 讨论(0)
  • 2020-11-28 06:52

    How about using LINQ To Objects to sort for you?

    Say you have a IList<Car>, and the car had an Engine property, I believe you could sort as follows:

    from c in list
    orderby c.Engine
    select c;
    

    Edit: You do need to be quick to get answers in here. As I presented a slightly different syntax to the other answers, I will leave my answer - however, the other answers presented are equally valid.

    0 讨论(0)
  • 2020-11-28 06:52

    The accepted answer by @DavidMills is quite good, but I think it can be improved upon. For one, there is no need to define the ComparisonComparer<T> class when the framework already includes a static method Comparer<T>.Create(Comparison<T>). This method can be used to create an IComparison on the fly.

    Also, it casts IList<T> to IList which has the potential to be dangerous. In most cases that I have seen, List<T> which implements IList is used behind the scenes to implement IList<T>, but this is not guaranteed and can lead to brittle code.

    Lastly, the overloaded List<T>.Sort() method has 4 signatures and only 2 of them are implemented.

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

    The below class implements all 4 List<T>.Sort() signatures for the IList<T> interface:

    using System;
    using System.Collections.Generic;
    
    public static class IListExtensions
    {
        public static void Sort<T>(this IList<T> list)
        {
            if (list is List<T>)
            {
                ((List<T>)list).Sort();
            }
            else
            {
                List<T> copy = new List<T>(list);
                copy.Sort();
                Copy(copy, 0, list, 0, list.Count);
            }
        }
    
        public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
        {
            if (list is List<T>)
            {
                ((List<T>)list).Sort(comparison);
            }
            else
            {
                List<T> copy = new List<T>(list);
                copy.Sort(comparison);
                Copy(copy, 0, list, 0, list.Count);
            }
        }
    
        public static void Sort<T>(this IList<T> list, IComparer<T> comparer)
        {
            if (list is List<T>)
            {
                ((List<T>)list).Sort(comparer);
            }
            else
            {
                List<T> copy = new List<T>(list);
                copy.Sort(comparer);
                Copy(copy, 0, list, 0, list.Count);
            }
        }
    
        public static void Sort<T>(this IList<T> list, int index, int count,
            IComparer<T> comparer)
        {
            if (list is List<T>)
            {
                ((List<T>)list).Sort(index, count, comparer);
            }
            else
            {
                List<T> range = new List<T>(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<T>(IList<T> sourceList, int sourceIndex,
            IList<T> 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<int> ints = new List<int>() { 1, 4, 5, 3, 2 };
        IList<Foo> foos = new List<Foo>()
        {
            new Foo(1),
            new Foo(4),
            new Foo(5),
            new Foo(3),
            new Foo(2),
        };
    
        ints.Sort();
        foos.Sort((x, y) => Comparer<int>.Default.Compare(x.Bar, y.Bar));
    }
    

    The idea here is to leverage the functionality of the underlying List<T> to handle sorting whenever possible. Again, most IList<T> implementations that I have seen use this. In the case when the underlying collection is a different type, fallback to creating a new instance of List<T> with elements from the input list, use it to do the sorting, then copy the results back to the input list. This will work even if the input list does not implement the IList interface.

    0 讨论(0)
  • 2020-11-28 06:52

    Found this thread while I was looking for a solution to the exact problem described in the original post. None of the answers met my situation entirely, however. Brody's answer was pretty close. Here is my situation and solution I found to it.

    I have two ILists of the same type returned by NHibernate and have emerged the two IList into one, hence the need for sorting.

    Like Brody said I implemented an ICompare on the object (ReportFormat) which is the type of my IList:

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

    I then convert the merged IList to an array of the same type:

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

    Then sort the array:

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

    Since one-dimensional array implements the interface System.Collections.Generic.IList<T>, the array can be used just like the original IList.

    0 讨论(0)
  • 2020-11-28 06:52

    In VS2008, when I click on the service reference and select "Configure Service Reference", there is an option to choose how the client de-serializes lists returned from the service.

    Notably, I can choose between System.Array, System.Collections.ArrayList and System.Collections.Generic.List

    0 讨论(0)
提交回复
热议问题