Osy#betaRun it on Osyrin: osyrin.com

Reference / Function

List Sort with a comparison

list.Sort((a, b) => int) → nothing; the list itself changes

Order a local List<T> IN PLACE by a comparison you write: a lambda taking two elements and answering an int — negative when the first goes first, 0 for a tie, positive when the second goes first. For orders with no single key, such as version numbers. Stable, like Sort() and OrderBy.

stable2 examples compiled by CIfunctioncollectionmutation

Summary#

list.Sort((a, b) => …) orders the list you are holding by a rule you write as a comparison — C#'s Sort(Comparison<T>). Reach for it when the order has no single key to hand to OrderBy: version numbers (1.10 comes after 1.9, which no string order says), a rank with exceptions, a "this field, unless…" rule.

When the order is a key, OrderBy(x => x.Field) says it more plainly — see List OrderBy (in-memory).

Signature#

list.Sort((a, b) => comparison);   // order the list by your comparison → nothing
list.Sort(cmp);                    // or any Func<T, T, int> value

Description#

The comparison takes two elements and answers an int:

It answersMeaning
negativea goes before b
0they tie — and keep the order they already had
positiveb goes before a

So (a, b) => a - b is ascending and (a, b) => b - a is descending. The comparison may read captured locals, call your own functions, and compare fields of class elements; it may also be a Func<T, T, int> held in a local or passed in as a parameter.

It is stable. Two elements the comparison calls equal keep their written order. That is not C#'s List<T>.Sort, which is an unstable introsort, but it is what Sort() and OrderBy already promise here, so all three sorting verbs follow one rule and the answer is the same on the server and in the browser.

Like Sort(), it changes the list in place and answers nothing: every other holder of the same list sees the new order. OrderBy is the copying counterpart.

A one-parameter lambda is refused — that is a sort key, and the refusal names OrderBy. IComparer<T> has no spelling here; pass a comparison instead.

Examples#

int CompareVersion(string a, string b) {
  var pa = a.Split('.');
  var pb = b.Split('.');
  for (int i = 0; i < 2; i++) {
    var d = int.Parse(pa[i]) - int.Parse(pb[i]);
    if (d != 0) return d;
  }
  return 0;
}

List<string> NewestFirst(List<string> versions) {
  var sorted = versions.ToList();                       // a copy, so the caller's list keeps its order
  sorted.Sort((a, b) => CompareVersion(b, a));          // 2.0, 1.10, 1.9, 1.2
  return sorted;
}
class Task { public string Title = ""; public int Priority; }

void ByPriority(List<Task> tasks) {
  // Equal priorities stay in the order they were added — the sort is stable.
  tasks.Sort((x, y) => x.Priority - y.Priority);
}

See also#

Related

List Sort, Reverse and RemoveAt (in place)

Reorder or shorten a local List<T> IN PLACE, changing the list you are holding rather than answering a new one. Sort()…

List OrderBy (in-memory)

Sort a local List<T> in memory by a key selector, returning a NEW sorted List<T> (the source is untouched). Ascending…

OrderBy / ThenBy

Sort a query by one key or several. `OrderBy`/`OrderByDescending` start the sort, `ThenBy`/`ThenByDescending` add…

Func<T, R>

A parameter or class field typed `Func<T, R>` takes a lambda and can be invoked for a result, so reusable code can be…