Summary#
list.Sort(), list.Reverse() and list.RemoveAt(i) change the list you are holding. They answer
nothing, exactly as their C# counterparts do. That is the whole difference from
List OrderBy (in-memory), which answers a new list and leaves the source as it was.
Reach for the in-place verb when anything else is holding the same list — a component member, a value
captured in a closure, a list handed to a helper. Those holders see the change. The rewrite people use
when they cannot say Sort() — xs = xs.OrderBy(k).ToList() — rebinds the name, so every other holder
goes on reading the old order.
Signature#
list.Sort(); // order the list by its elements → nothing
list.Reverse(); // flip the order → nothing
list.RemoveAt(i); // delete the element at position i → nothingDescription#
All three are List<T> verbs. An array (T[]) is fixed-size and has none of them, which is C#'s rule
too — the refusal names List<T> and OrderBy so the fix is one edit.
Sort() orders by the elements themselves, so the element type has to be a comparable scalar — a
number, string, date or enum. A list of class values has no natural order, and that is a compile error
naming the fix rather than a fault at run time. Sort by a field with OrderBy(x => x.Field).
The order is the one OrderBy uses, so the two verbs never disagree about what the order is; they
differ only in whether your list moved. It is ordinal, by code point — not culture-aware, unlike C#'s
own List<string>.Sort() — because an order that depends on the machine's locale is not one every engine
can promise. Equal elements keep their written order (a stable sort).
There is no comparer argument. C#'s Sort(Comparison<T>) and Sort(IComparer<T>) have no spelling
here — Osy# has neither delegate values nor an IComparer type. Sorting by a rule of your own is
OrderBy(x => key), and passing a comparer is refused rather than quietly ignored.
Reverse() on a List<T> reverses in place. Inside a LINQ chain the same word still means the
sequence verb that answers a reversed copy (list.Reverse().Take(2)), and on an array it always does —
which is C#'s own split between the instance method and the extension.
RemoveAt(i) deletes by position; Remove(x) deletes by value and RemoveAll(x => …) deletes every
match. An index outside the list throws, as in C#.
Examples#
List<int> Ranked() {
var scores = new List<int>();
scores.Add(30);
scores.Add(4);
scores.Add(100);
var alsoScores = scores; // a second name for the SAME list
scores.Sort(); // 4, 30, 100 — and `alsoScores` sees it, because nothing was copied
alsoScores.RemoveAt(0); // drop the lowest
alsoScores.Reverse(); // 100, 30
return scores;
}class Entry { public string Name; public int Score; }
List<Entry> ByScore(List<Entry> entries) {
// `Sort()` would be refused here: an Entry has no natural order. Name the key instead.
return entries.OrderByDescending(e => e.Score).ToList();
}See also#
- List OrderBy (in-memory) — the copying counterpart, and how to sort by a key
- List indexer — reading and writing a position
- Sequence fields on a class — the whole
List<T>/HashSet<T>/Dictionary<K,V>surface