Die akzeptierte Antwort von @DavidMills ist ziemlich gut, aber ich denke, dass es verbessert werden kann. Zum einen muss die Klasse ComparisonComparer<T>
nicht definiert werden, wenn das Framework bereits eine statische Methode Comparer<T>.Create(Comparison<T>)
enthält. Diese Methode kann verwendet werden, um eine IComparison
on the fly zu erstellen.
Auch wirft es IList<T>
zu IList
, die potenziell gefährlich sein kann. In den meisten Fällen, die ich gesehen habe, List<T>
, die implementiert IList
wird hinter den Kulissen verwendet, um IList<T>
zu implementieren, aber das ist nicht garantiert und kann zu spröden Code führen.
Schließlich hat die überladene List<T>.Sort()
Methode 4 Signaturen und nur 2 von ihnen sind implementiert.
List<T>.Sort()
List<T>.Sort(Comparison<T>)
List<T>.Sort(IComparer<T>)
List<T>.Sort(Int32, Int32, IComparer<T>)
Die unten Klasse implementiert alle 4 List<T>.Sort()
Unterschriften für die IList<T>
Schnittstelle:
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(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));
}
Die Idee dabei ist, die Funktionalität der zugrunde liegenden List<T>
zu nutzen, wann immer möglich zu handhaben zu sortieren. Die meisten Implementierungen von IList<T>
, die ich gesehen habe, verwenden dies. Wenn die zugrunde liegende Sammlung ein anderer Typ ist, erstellen Sie eine neue Instanz von List<T>
mit Elementen aus der Eingabeliste, verwenden Sie sie, um die Sortierung durchzuführen, und kopieren Sie dann die Ergebnisse zurück in die Eingabeliste. Dies funktioniert auch dann, wenn die Eingabeliste die Schnittstelle IList
nicht implementiert.
Warum würden Sie in erster Linie eine IList zurückgeben? Von einem WCF-Dienst? – DaeMoohn