There's another important and extremely simple way, unless you absolutely require that you sort in-place: use LINQ to Objects. For example:
var orderedByName = cars.OrderBy(car => car.Name).ToList();
You can order by multiple projections, and in a varied fashion, like this:
var complex = cars.OrderByDescending(car => car.Year)
.ThenBy(car => car.Model)
.ThenByDescending(car => car.Make)
.ToList();
I've only put the ToList at the end to create a List<Car> at the end - if you only need to iterate over the results though, you can let it perform the ordering lazily:
var query = cars.OrderByDescending(car => car.Year)
.ThenBy(car => car.Model)
.ThenByDescending(car => car.Make);
foreach (var car in cars)
{
// Use car
}
Personally I find this the most flexible way of sorting. Otherwise, using IComparer<T> and Comparison<T> are the next most flexible, as anyone can order that way. IComparable<T> requires the class itself to decide how items are going to be ordered, and you can only implement it once, which makes it somewhat inflexible.
IEquatable<T> is used for comparing items for equality, so is used for things like HashSet<T>, not for ordering.