Generic List<T> Sorting

Generic List Sorting

為了實作 Generic List<T> 的排序方法,以建立 Product 類別作為示範,Product 類別擁有 int 型態的 ID 屬性、string 型態的 Name 屬性、double 型態的 Pricce 屬性、DateTime 型態的 ShipDate 屬性:


public class Product : IComparable<Product>
{
    public int ID{ get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public DateTime ShipDate { get; set; }
}

定義 ProductSortFields 列舉,為需要排序的屬性作定義:


public enum ProductSortFields
{
    ID, Name, Price, ShipDate
}

在 Product 類別繼承 IComparable<Product> 介面,並實作 CompareTo 方法,定義如何定比較兩個 Product 類別物件:


public class Product : IComparable<Product>
{
    public int ID{ get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public DateTime ShipDate { get; set; }

    #region IComparable Members

    public int CompareTo(Product obj)
    {
        return ID.CompareTo(obj.ID);
    }

    public int CompareTo(Product p, ProductSortFields field)
    {
        switch (field)
        {
            case ProductSortFields.ID:
                return ID.CompareTo(p.ID);
            case ProductSortFields.Name:
                return Name.CompareTo(p.Name);
            case ProductSortFields.Price:
                return Price.CompareTo(p.Price);
            case ProductSortFields.ShipDate:
                return ShipDate.CompareTo(p.ShipDate);
            default:
                return ID.CompareTo(p.ID);
        }
    }

    #endregion

    public override string ToString()
    {
        return string.Format("ID: {0}, Name: {1}, Price: {2}, ShipDate: {3}", ID, Name, Price, ShipDate.ToShortDateString());
    }
}

建立 ProductComparer 類別並繼承 IComparer<Product> 介面,實作 Compare 方法定義排序欄位與排序順序,並呼叫 Product 類別 CompareTo 方法來比較兩 Product 類別物件。


public class ProductComparer : IComparer<Product>
{
    public ProductSortFields Field { get; set; }
    public SortOrder Order { get; set; }

    public ProductComparer(ProductSortFields field, SortOrder order)
    {
        Field = field;
        Order = order;
    }

    #region IComparer<Product> Members

    public int Compare(Product p1, Product p2)
    {
        if (Order == SortOrder.Ascending)
        {
            return p1.CompareTo(p2, Field);
        }
        return p2.CompareTo(p1, Field);
    }

    #endregion
}

實際操作範例:


// 新增 List<Product>
List<Product> pplist = new List<Product>
{
    new Product() { ID = 1, Name = "A", Price = 7, ShipDate = new DateTime(2006, 1, 19) },
    new Product() { ID = 7, Name = "C", Price = 237, ShipDate = new DateTime(2006, 10, 17) },
    new Product() { ID = 4, Name = "B", Price = 17, ShipDate = new DateTime(2007, 2, 12) },
    new Product() { ID = 5, Name = "D", Price = 57, ShipDate = new DateTime(2005, 9, 11) }
};

// 依照 ID 欄位,升冪排序
pplist.Sort(new ProductComparer(ProductSortFields.ID, SortOrder.Ascending));
foreach (Product product in pplist)
{
    Console.WriteLine(product.ToString());
}

// 依照 Name 欄位,降冪排序
pplist.Sort(new ProductComparer(ProductSortFields.Name, SortOrder.Descending));
foreach (Product product in pplist)
{
    Console.WriteLine(product.ToString());
}

// 依照 Price 欄位,降冪排序
pplist.Sort(new ProductComparer(ProductSortFields.Price, SortOrder.Descending));
foreach (Product product in pplist)
{
    Console.WriteLine(product.ToString());
}

// 依照 ShipDate 欄位,升冪排序
pplist.Sort(new ProductComparer(ProductSortFields.ShipDate, SortOrder.Ascending));
foreach (Product product in pplist)
{
    Console.WriteLine(product.ToString());
}

結果輸出:


// 依照 ID 欄位,升冪排序
ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19
ID: 4, Name: B, Price: 17, ShipDate: 2007/2/12
ID: 5, Name: D, Price: 57, ShipDate: 2005/9/11
ID: 7, Name: C, Price: 237, ShipDate: 2006/10/17

// 依照 Name 欄位,降冪排序
ID: 5, Name: D, Price: 57, ShipDate: 2005/9/11
ID: 7, Name: C, Price: 237, ShipDate: 2006/10/17
ID: 4, Name: B, Price: 17, ShipDate: 2007/2/12
ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19

// 依照 Price 欄位,降冪排序
ID: 7, Name: C, Price: 237, ShipDate: 2006/10/17
ID: 5, Name: D, Price: 57, ShipDate: 2005/9/11
ID: 4, Name: B, Price: 17, ShipDate: 2007/2/12
ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19

// 依照 ShipDate 欄位,升冪排序
ID: 5, Name: D, Price: 57, ShipDate: 2005/9/11
ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19
ID: 7, Name: C, Price: 237, ShipDate: 2006/10/17
ID: 4, Name: B, Price: 17, ShipDate: 2007/2/12