@DavidMills 接受的答案非常好,但我认为可以改进。ComparisonComparer<T>
一方面,当框架已经包含静态方法时,不需要定义类Comparer<T>.Create(Comparison<T>)
。此方法可用于动态创建IComparison
。
此外,它会投射IList<T>
到IList
有潜在危险的地方。在我见过的大多数情况下,在幕后使用List<T>
哪个实现来实现,但这并不能保证并且可能导致代码脆弱。IList
IList<T>
最后,重载的List<T>.Sort()
方法有 4 个签名,其中只有 2 个被实现。
List<T>.Sort()
List<T>.Sort(Comparison<T>)
List<T>.Sort(IComparer<T>)
List<T>.Sort(Int32, Int32, IComparer<T>)
下面的类实现List<T>.Sort()
了接口的所有 4 个签名IList<T>
:
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];
}
}
}
用法:
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));
}
这里的想法是尽可能利用底层的功能List<T>
来处理排序。同样,IList<T>
我见过的大多数实现都使用它。在底层集合是不同类型的情况下,回List<T>
退到从输入列表中创建一个带有元素的新实例,使用它进行排序,然后将结果复制回输入列表。即使输入列表没有实现IList
接口,这也将起作用。