-1

If I have a List<T>, I can sort it in place using for example

myList.Sort((x,y) => x.MyComparisonMethod(y));

If I have an IList<T>, I can sort it into a new list using

var sortedIList = unsortedIList.OrderBy(x => x.SortingValue);

How can I sort an IList<T> in place?

I am using C# .NET 4.5.1.

tomsv
  • 7,207
  • 6
  • 55
  • 88
  • 1
    Why do you want to do this? What situation are you in that `unsortedIList = unsortedIList.OrderBy(x => x.SortingValue);` won't solve? – David Arno Jun 19 '15 at 09:48
  • _" I can sort it into a new list using"_ no, that's not the case, `OrderBy` doesnt return a list, you have to call `ToList` to create a new list. Is your question how to use `List.Sort` with an `IList` instead of a `List`? – Tim Schmelter Jun 19 '15 at 09:50
  • 2
    You'll have to create a `Sort` method and use it. Take one of those used by Mono for example. – xanatos Jun 19 '15 at 09:57

3 Answers3

0

Write your own extension method using ArrayList.Adapter as IList<T> wrapper and your own CustomComparer starting from some Comparison delegate:

public static class IListExtensions
{
    public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
    {
        ArrayList.Adapter((IList)list).Sort(new CustomComparer<T>(comparison));
    }
}
Francesco De Lisi
  • 1,493
  • 8
  • 20
  • Why the -1? What's the purpose of a -1 without explanation? – Francesco De Lisi Jun 19 '15 at 09:59
  • I actually like this, but couldn't find `CustomComparer` in the framework. Instead I used `Comparer.Create(comparison)` which seems to do what is intended here. – dana Aug 18 '16 at 22:24
-1

" I can sort it into a new list using" no, that's not the case, OrderBy doesnt return a list, you have to call ToList to create a new list. Is your question how to use List.Sort with an IList<T> instead of a List<T>?

You can write an extension method for IList<T>:

public static IList<T> Sort<T>(this IEnumerable<T> sequence, IComparer<T> comparer = null)
{
    var seqList = sequence as List<T>;
    if (seqList != null)
    {
        seqList.Sort((IComparer<T>)comparer);
        return seqList;
    }

    var seqArray = sequence as T[];
    if (seqArray != null)
    {
        Array.Sort(seqArray, (IComparer<T>)comparer);
        return seqArray;
    }

    return sequence.OrderBy(t => t, (IComparer<T>)comparer).ToList();
}

Now you can use Sort on lists, arrays or any other kind of sequence:

IList<string> strings = new[] { "B", "A", "C" };
strings.Sort();

Update: if you just want one for arrays or lists you can use:

public static void Sort<T>(this IList<T> sequence, IComparer<T> comparer = null)
{
    var seqList = sequence as List<T>;
    if (seqList != null)
    {
        seqList.Sort((IComparer<T>)comparer);
        return;
    }

    var seqArray = sequence as T[];
    if (seqArray != null)
    {
        Array.Sort(seqArray, (IComparer<T>)comparer);
    }
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 3
    This seems to have slightly confusing behaviour. It sorts in place for `List` and `T[]`, but it returns a new list for anything else. – Charles Mager Jun 19 '15 at 09:58
  • @CharlesMager: you could make the parameter an `IList` and remove `return sequence.OrderBy(t => t, (IComparer)comparer).ToList()` if you don't want that. I just wanted to include it because OP has mentioned it. It's the all-inclusive approach. The return value is also redundant then. – Tim Schmelter Jun 19 '15 at 10:00
  • Then you'd have the 'not all code paths return a value' problem as `IList != List` - which is the crux of the question, really. How do you sort an `IList` in place when it might not be `List`? – Charles Mager Jun 19 '15 at 10:01
  • @CharlesMager: why? If you want one just for `IList` you can make the method `void`. Both, lists and arrays support the void method `Sort`. Edited my answer to show it. – Tim Schmelter Jun 19 '15 at 10:03
  • ah, yes. Being a bit dumb there... but the point still stands that if it isn't `T[]` or `List` it won't do any sorting. What if I passed in `Collection`, `BindingList` etc? – Charles Mager Jun 19 '15 at 10:05
  • @CharlesMager: first you were complainig that the method does too much now that it does too little. OP seems to want only one that supports `IList` and sorts "in place", so without creating a new list. – Tim Schmelter Jun 19 '15 at 10:08
  • Which is my point - this doesn't support `IList`, it supports 2 implementations of it. I'm not deliberately trying to be argumentative, I just don't think it answers the question. – Charles Mager Jun 19 '15 at 10:09
  • @CharlesMager: sorry, i'm hard of understanding today. It accepts an `IList` which could f.e. be a `List` or a `string[]` and it sorts them in place. What else could it support when OP asks "How can I sort an IList in place"? It does not support an `IList`, that's right. But that wasn't asked. – Tim Schmelter Jun 19 '15 at 10:13
  • But it could also be a `Collection`, `BindingList`, `ObservableCollection`, any other of the dozens of implementations of `IList` in the BCL, or a custom implementation. These won't be sorted, but the contract implies they would. Apologies if I'm sounding argumentative, as I don't have a solution short of 'implement sort yourself'. – Charles Mager Jun 19 '15 at 10:19
  • @CharlesMager: you cannot support all since those collections don't support sorting by default. What you could do is to throw a `NotSupportedException` at runtime if the type is not a list or array. But again, that wasn't asked anyway. If you need to support it the easiest way is to use LINQ. For example: `new BindingList(seqColl.OrderBy(x => x, comparer).ToList())` – Tim Schmelter Jun 19 '15 at 10:43
  • I'm still struggling to see how you claim it's not asked - the question is literally *"How can I sort an IList in place?"* - there's no mention it's limited to any specific implementations. There are lots of generic solutions in the duplicates. – Charles Mager Jun 19 '15 at 10:46
-2

I suspect you're referring to the fact that your OrderBy won't compile. That's because it returns an IOrderedEnumerable, which is not an IList, you'd have to perform ToList() afterwards to convert it back to an IList implementation:

var sortedIList = unsortedIList.OrderBy(x => x.SortingValue).ToList();

And if you want to use your own IComparer:

var sortedIList = unsortedIList.OrderBy(x => x.SortingValue, new MyComparer()).ToList();
Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148