How to sort an IEnumerable<string>

Solution 1:

The same way you'd sort any other enumerable:

var result = myEnumerable.OrderBy(s => s);

or

var result = from s in myEnumerable
             orderby s
             select s;

or (ignoring case)

var result = myEnumerable.OrderBy(s => s,
                                  StringComparer.CurrentCultureIgnoreCase);

Note that, as is usual with LINQ, this creates a new IEnumerable<T> which, when enumerated, returns the elements of the original IEnumerable<T> in sorted order. It does not sort the IEnumerable<T> in-place.


An IEnumerable<T> is read-only, that is, you can only retrieve the elements from it, but cannot modify it directly. If you want to sort a collection of strings in-place, you need to sort the original collection which implements IEnumerable<string>, or turn an IEnumerable<string> into a sortable collection first:

List<string> myList = myEnumerable.ToList();
myList.Sort();

Based on your comment:

_components = (from c in xml.Descendants("component")
               let value = (string)c
               orderby value
               select value
              )
              .Distinct()
              .ToList();

or

_components = xml.Descendants("component")
                 .Select(c => (string)c)
                 .Distinct()
                 .OrderBy(v => v)
                 .ToList();

or (if you want to later add more items to the list and keep it sorted)

_components = xml.Descendants("component")
                 .Select(c => (string)c)
                 .Distinct()
                 .ToList();

_components.Add("foo");
_components.Sort();

Solution 2:

It is impossible, but it isn't.

Basically, any sort method is going to copy your IEnumerable into a List, sort the List and then return to you the sorted list, which is an IEnumerable as well as an IList.

This means you lose the "continue infinitely" property of an IEnumerable, but then you couldn't sort one like that anyway.

Solution 3:

myEnumerable = myEnumerable.OrderBy(s => s);

Solution 4:

We can't always do it in-place, but we detect when it's possible:

IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, IComparer<T> cmp)
{
  List<T> listToSort = (src is List<T>) ? (List<T>)src : new List<T>(src);
  listToSort.Sort(cmp);
  return listToSort;
}
IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src, Comparison<T> cmp)
{
  return SortInPlaceIfCan(src, new FuncComparer<T>(cmp));
}
IEnumerable<T> SortInPlaceIfCan(IEnumerable<T> src)
{
  return SortInPlaceIfCan(src, Comparer<T>.Default);
}

This uses the following handy struct:

internal struct FuncComparer<T> : IComparer<T>
{
  private readonly Comparison<T> _cmp;
  public FuncComparer(Comparison<T> cmp)
  {
      _cmp = cmp;
  }
  public int Compare(T x, T y)
  {
      return _cmp(x, y);
  }
}