Die akzeptierte Antwort von @DavidMills ist ziemlich gut, aber ich denke, sie kann verbessert werden. Zum einen muss die ComparisonComparer<T>
Klasse nicht definiert werden , wenn das Framework bereits eine statische Methode enthält Comparer<T>.Create(Comparison<T>)
. Mit dieser Methode können Sie eine erstellenIComparison
on-the-fly .
Außerdem wirft es, IList<T>
für IList
die das Potenzial besteht, gefährlich zu sein. In den meisten Fällen, die ich gesehen habe, wird List<T>
das , was implementiert IList
wird, hinter den Kulissen verwendet, um zu implementierenIList<T>
, aber dies ist nicht garantiert und kann zu sprödem Code führen.
Schließlich hat die überladene List<T>.Sort()
Methode 4 Signaturen und nur 2 davon sind implementiert.
List<T>.Sort()
List<T>.Sort(Comparison<T>)
List<T>.Sort(IComparer<T>)
List<T>.Sort(Int32, Int32, IComparer<T>)
Die folgende Klasse implementiert alle 4 List<T>.Sort()
Signaturen für die IList<T>
Schnittstelle:
using System;
using System.Collections.Generic;
public static class IListExtensions
{
public static void Sort<T>(this IList<T> list)
{
if (list is List<T>)
{
((List<T>)list).Sort();
}
else
{
List<T> copy = new List<T>(list);
copy.Sort();
Copy(copy, 0, list, 0, list.Count);
}
}
public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
{
if (list is List<T>)
{
((List<T>)list).Sort(comparison);
}
else
{
List<T> copy = new List<T>(list);
copy.Sort(comparison);
Copy(copy, 0, list, 0, list.Count);
}
}
public static void Sort<T>(this IList<T> list, IComparer<T> comparer)
{
if (list is List<T>)
{
((List<T>)list).Sort(comparer);
}
else
{
List<T> copy = new List<T>(list);
copy.Sort(comparer);
Copy(copy, 0, list, 0, list.Count);
}
}
public static void Sort<T>(this IList<T> list, int index, int count,
IComparer<T> comparer)
{
if (list is List<T>)
{
((List<T>)list).Sort(index, count, comparer);
}
else
{
List<T> range = new List<T>(count);
for (int i = 0; i < count; i++)
{
range.Add(list[index + i]);
}
range.Sort(comparer);
Copy(range, 0, list, index, count);
}
}
private static void Copy<T>(IList<T> sourceList, int sourceIndex,
IList<T> destinationList, int destinationIndex, int count)
{
for (int i = 0; i < count; i++)
{
destinationList[destinationIndex + i] = sourceList[sourceIndex + i];
}
}
}
Verwendung:
class Foo
{
public int Bar;
public Foo(int bar) { this.Bar = bar; }
}
void TestSort()
{
IList<int> ints = new List<int>() { 1, 4, 5, 3, 2 };
IList<Foo> foos = new List<Foo>()
{
new Foo(1),
new Foo(4),
new Foo(5),
new Foo(3),
new Foo(2),
};
ints.Sort();
foos.Sort((x, y) => Comparer<int>.Default.Compare(x.Bar, y.Bar));
}
Hier geht es darum, die Funktionalität des Basiswerts List<T>
zu nutzen, um die Sortierung nach Möglichkeit durchzuführen. Wiederum verwenden die meisten IList<T>
Implementierungen, die ich gesehen habe, dies. Wenn es sich bei der zugrunde liegenden Auflistung um einen anderen Typ handelt, greifen Sie auf das Erstellen einer neuen Instanz List<T>
mit Elementen aus der Eingabeliste zurück, verwenden Sie diese zum Sortieren und kopieren Sie die Ergebnisse zurück in die Eingabeliste. Dies funktioniert auch dann, wenn die Eingabeliste die IList
Schnittstelle nicht implementiert .