# List Sort with a comparison

> 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.

<!-- id: function-list-sort-comparison · area: function · stability: stable · html: https://osysharp.com/reference/function/list-sort-comparison/ -->

## Summary        {#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)](https://osysharp.com/reference/function/list-orderby/).

## Signature      {#signature}
```osy syntax
list.Sort((a, b) => comparison);   // order the list by your comparison → nothing
list.Sort(cmp);                    // or any Func<T, T, int> value
```

## Description    {#description}
The comparison takes **two elements** and answers an `int`:

| It answers | Meaning |
|---|---|
| negative | `a` goes before `b` |
| `0` | they tie — and keep the order they already had |
| positive | `b` 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       {#examples}
```osy title="newest version first — an order with no single key" test app=list-sort-comparison
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;
}
```

```osy title="ties keep their order" test app=list-sort-comparison-stable
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       {#see-also}
- [List Sort, Reverse and RemoveAt (in place)](https://osysharp.com/reference/function/list-sort/) — `Sort()` by the elements' natural order, `Reverse()`, `RemoveAt(i)`
- [List OrderBy (in-memory)](https://osysharp.com/reference/function/list-orderby/) — the copying counterpart, sorting by a key
- [OrderBy / ThenBy](https://osysharp.com/reference/query/ordering/) — ordering a query, which runs in the database
