对IList排序的最佳方法是什么<;T>;在.NET2.0中?

对IList排序的最佳方法是什么<;T>;在.NET2.0中?,.net,.net-2.0,.net,.net 2.0,我有一个需要排序的IList,如果可能的话,我宁愿不复制列表。我注意到,ArrayList有一个Adapter静态方法,它包装传递的列表而不复制它,但是这需要一个IList,我有一个IList。从System.Collections.Generic.IList转换为System.Collections.IList并使用Adapter方法是否安全 请注意,这是.Net 2.0,因此LINQ不是一个选项。在Paul Fox的博客中,我推荐“如何对IList排序”一文: 为了以防万一,我将把这篇文章复

我有一个需要排序的
IList
,如果可能的话,我宁愿不复制列表。我注意到,
ArrayList
有一个
Adapter
静态方法,它包装传递的列表而不复制它,但是这需要一个
IList
,我有一个
IList
。从
System.Collections.Generic.IList转换为
System.Collections.IList
并使用
Adapter
方法是否安全


请注意,这是.Net 2.0,因此LINQ不是一个选项。

在Paul Fox的博客中,我推荐“如何对IList排序”一文:

为了以防万一,我将把这篇文章复制到这里:


如何对通用IList进行排序

更新

您可以阅读并更新有关的帖子。许多人会喜欢更新后的帖子中提到的方法

对泛型IList进行排序

我试图对一个通用的IList进行排序,并找到了一个相当简单的方法

第一步

您需要为IList中包含的类型实现IComparable。对于这个例子,我将使用一种简单的语言Dto类

public class LanguageDto : IComparable {
 private String name;
 public string Name { get { return name; } set { name = value; } }

 public LanguageDto(string name) {
     this.name = name;
 }

 #region IComparable Members
 public int CompareTo(object obj) {
     if (obj is LanguageDto) {
     LanguageDto language = (LanguageDto)obj;
     return this.name.CompareTo(language.name);
     }
     throw new ArgumentException(string.Format("Cannot compare a LanguageDto to an {0}", obj.GetType().ToString()));
 }
 #endregion
}
步骤2

把你的行李分类。为此,将使用ArrayList.Adapter()方法传入IList,然后调用Sort方法。就像这样

ArrayList.Adapter((IList)languages).Sort();
注:语言类型为“IList”

然后,语言应该是您类型的排序列表

不能将IList(T)强制转换为IList

使用Reflector进行嗅探后,ArrayList.Adapter(IList).Sort()将首先将列表复制到对象数组,对数组进行排序,然后将数组复制回列表:

object[] array = new object[count];
this.CopyTo(index, array, 0, count);
Array.Sort(array, 0, count, comparer);
for (int i = 0; i < count; i++)
{
    this._list[i + index] = array[i];
}
object[]数组=新对象[count];
this.CopyTo(索引、数组、0、计数);
排序(数组,0,计数,比较器);
for(int i=0;i
如果列表中的T(T)是值类型,则可能会产生装箱开销

如果需要更改列表中对象的顺序,可以采用类似方法:

IList<object> unsorted = ...
List<object> sorted = new List<object>(unsorted);
sorted.Sort(); 
for (int i = 0; i < unsorted.Countt; i++)
{
    unsorted[i] = sorted[i];
}
IList unsorted=。。。
已排序列表=新列表(未排序);
sorted.Sort();
for(int i=0;i

如果列表太大(如数亿项),您无法在内存中创建额外的副本,我建议您首先使用列表(T)或实现您最喜欢的就地排序算法。

我知道它不是.NET 2.0,但我非常喜欢LINQ,并会尽可能支持它:)

IList<object> unsorted = ...
IList<object> sortedList = unsorted.Orderby(x => x.Tostring()).Tolist();
简单排序:

var sortedProducts =
    from p in products
    orderby p.ProductName
    select p;

ObjectDumper.Write(sortedProducts);
string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

var sortedDigits =
    from d in digits 
    orderby d.Length, d
    select d;
按多个条件排序:

var sortedProducts =
    from p in products
    orderby p.ProductName
    select p;

ObjectDumper.Write(sortedProducts);
string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

var sortedDigits =
    from d in digits 
    orderby d.Length, d
    select d;

两个例子都来自

,因为排序方法不在ILIST接口上,您可以考虑创建自己的:

interface ISortableList<T> : IList<T>
{
    void Sort();
    void Sort(IComparer<T> comparer);
}

class SortableList<T> : List<T>, ISortableList<T> { }

/* usage */
void Example(ISortedList<T> list)
{
    list.Sort();
    list.Sort(new MyCustomerComparer());
}
接口可移植列表:IList
{
无效排序();
无效排序(IComparer比较器);
}
类SortableList:List,ISortableList{}
/*用法*/
无效示例(ISortedList列表)
{
list.Sort();
排序(新的MyCustomerComparer());
}
通常,在方法中指定的参数类型应该是实际需要调用的成员的最小公分母。如果您确实需要调用Sort()方法,那么您的参数应该定义该成员。否则,您可能应该将其加载到另一个可以做您想做的事情的对象中,例如:

void Example(IList<T> list)
{
    list = new List<T>(list).Sort();
}
void示例(IList列表)
{
list=新列表(list.Sort();
}
这实际上应该非常快,几乎可以肯定比编写自己的自定义内联排序算法还要快。

IList unsorted=。。。
IList<object> unsorted = ...
IList<object> sortedList = unsorted.Orderby(x => x.Tostring()).Tolist();
IList sortedList=unsorted.Orderby(x=>x.Tostring()).Tolist();
这将在对象的特定字段上提供排序列表。

如果需要对不同类的列表(而不是ILists)进行排序,而不需要为所有类创建单独的比较器类,并且仍然保持实体类的干净(您不希望实现IComparable),则可以使用以下选项(与.NET 2.0兼容):

公共类动态比较程序:IComparer
{
私有函数计算函数;
专用多路复用器;
私有函数比较函数;
公共动态比较程序(Func calculateFunc,bool reverse=false)
{
if(calculateFunc==null)
{
抛出新异常(“委托函数'calculateFunc'不能为null”);
}
this.calculateFunc=calculateFunc;
这个.calculateMultiplier=反向?-1:1;
this.compareFunc=null;
}
公共动态比较程序(Func compareFunc)
{
if(calculateFunc==null)
{
抛出新异常(“委托函数'compareFunc'不能为null”);
}
this.calculateFunc=null;
this.compareFunc=compareFunc;
}
公共整数比较(TX,TY)
{
if(calculateFunc!=null)
{
return(calculateFunc(x)-calculateFunc(y))*this.calculateMultiplier;
}
if(compareFunc!=null)
{
返回compareFunc(x,y);
}
抛出新异常(“不可能进行比较,因为未指定比较或计算函数。”);
}
}
如果您使用的是.NET 2.0(可在上找到),则还需要Func委托:

public委托TResult Func(T);
公共代表TResult Func(T,U);
用法:

myList.Sort(new DynamicComparer<MyClass>(x => x.MyIntProperty) // Ascending
myList.Sort(new DynamicComparer<MyClass>(x => x.MyIntProperty, true) // Descending
myList.Sort(新的DynamicComparer(x=>x.MyIntProperty)//升序
排序(新的DynamicComparer(x=>x.MyIntProperty,true)//降序
一些简单的单元测试:

[TestClass()]
public class DynamicComparerTU
{
    [TestMethod()]
    public void SortIntList()
    {
        // Arrange
        dynamic myIntArray = new int[] {
            4,
            1,
            9,
            0,
            4,
            7
        };
        dynamic myIntList = new List<int>(myIntArray);

        // Act
        int temp = 0;
        for (int write = 0; write <= myIntArray.Length - 1; write++)
        {
            for (int sort = 0; sort <= myIntArray.Length - 2; sort++)
            {
                if (myIntArray(sort) > myIntArray(sort + 1))
                {
                    temp = myIntArray(sort + 1);
                    myIntArray(sort + 1) = myIntArray(sort);
                    myIntArray(sort) = temp;
                }
            }
        }

        myIntList.Sort(new DynamicComparer<int>(x => x));

        // Assert
        Assert.IsNotNull(myIntList);
        Assert.AreEqual(myIntArray.Length, myIntList.Count);
        for (int i = 0; i <= myIntArray.Length - 1; i++)
        {
            Assert.AreEqual(myIntArray(i), myIntList(i));
        }
    }

    [TestMethod()]
    public void SortStringListByLength()
    {
        // Arrange
        dynamic myStringArray = new string[] {
            "abcd",
            "ab",
            "abcde",
            "a",
            "abc"
        };
        dynamic myStringList = new List<string>(myStringArray);

        // Act
        myStringList.Sort(new DynamicComparer<string>(x => x.Length));

        // Assert
        Assert.IsNotNull(myStringList);
        Assert.AreEqual(5, myStringList.Count);
        Assert.AreEqual("a", myStringList(0));
        Assert.AreEqual("ab", myStringList(1));
        Assert.AreEqual("abc", myStringList(2));
        Assert.AreEqual("abcd", myStringList(3));
        Assert.AreEqual("abcde", myStringList(4));
    }

    [TestMethod()]
    public void SortStringListByLengthDescending()
    {
        // Arrange
        dynamic myStringArray = new string[] {
            "abcd",
            "ab",
            "abcde",
            "a",
            "abc"
        };
        dynamic myStringList = new List<string>(myStringArray);

        // Act
        myStringList.Sort(new DynamicComparer<string>(x => x.Length, true));

        // Assert
        Assert.IsNotNull(myStringList);
        Assert.AreEqual(5, myStringList.Count);
        Assert.AreEqual("abcde", myStringList(0));
        Assert.AreEqual("abcd", myStringList(1));
        Assert.AreEqual("abc", myStringList(2));
        Assert.AreEqual("ab", myStringList(3));
        Assert.AreEqual("a", myStringList(4));
    }
}
[TestClass()]
公共类动态比较程序
{
[TestMethod()]
公共无效排序列表()
{
//安排
动态myIntArray=new int[]{
4.
1.
9,
0,
4.
7.
};
动态myIntList=新列表(myIntArray);
//表演
内部温度=0;
对于(int write=0;write x));
//断言
Assert.IsNotNull(myIntList);