• C# 3.0 CookBook:三、类与结构(2):类型支持排序


    问题

       要使自定义类型能够像一个List<T>或SortedList<K,V>结构那样可排序。一般情况下,我们会倾向于使用List<T>.Sort方法或SortedList<K,V>的内部排序机制,来定制由用户自定义数据类型组成的数组中的排序规则。此外,用户可能需要在SortedList集合中使用此类型。

    解决方案

        例3-1示范了怎样实现IComparable<T>接口。例3-1中的Square类实现了该接口使其能够像List<T>和SortedList<K,V>集合那样对Square对象进行排序和搜索。

    //示例3-1.实现IComparable<T>接口,让类型可以排序
    public class Square : IComparable<Square>
    {
        public Square() { }
        public Square(int height, int width)
        {
            this.Height = height;
            this.Width = width;
        }
        public int Height { get; set; }
        public int Width { get; set; }
        public int CompareTo(object obj)
        {
            Square square = obj as Square;
            if (square != null)
                return CompareTo(square);
            throw
            new ArgumentException("Both objects being compared must be of type Square.");
        }
        public override string ToString()
        {
            return ("Height:" + this.Height + " Width:" + this.Width);
        }
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            Square square = obj as Square;
            if (square != null)
                return this.Height == square.Height;
            return false;
        }
        public override int GetHashCode()
        {
            return this.Height.GetHashCode() | this.Width.GetHashCode();
        }
        public static bool operator ==(Square x, Square y)
        {
            return x.Equals(y);
        }
        public static bool operator !=(Square x, Square y)
        {
            return !(x == y);
        }
        public static bool operator <(Square x, Square y)
        {
            return (x.CompareTo(y) < 0);
        }
        public static bool operator >(Square x, Square y)
        {
            return (x.CompareTo(y) > 0);
        }
        #region IComparable<Square> Members
        public int CompareTo(Square other)
        {
            long area1 = this.Height * this.Width;
            long area2 = other.Height * other.Width;
            if (area1 == area2)
                return 0;
            else if (area1 > area2)
                return 1;
            else if (area1 < area2)
                return -1;
            else
                return -1;
        }
        #endregion
    }

    讨论

        依靠在自定义类型(或结构)中实现IComparable<T>接口,可以得到List<T>和SortedList<K,V>类一样的排序算法的性能优势。排序算法内置在这些类定义中,用户需要做的就是实现IComparable<T>.CompareTo方法,通过代码告诉他们怎样对用户自定义的类进行排序。

    //示例3-2. 实现IComparable<T>接口,让类型可以排序
    public class CompareHeight : IComparer<Square>
    {
        public int Compare(object firstSquare, object secondSquare)
        {
            Square square1 = firstSquare as Square;
            Square square2 = secondSquare as Square;
            if (square1 == null || square2 == null)
                throw (new ArgumentException("Both parameters must be of type Square."));
            else
                return Compare(firstSquare, secondSquare);
        }
        #region IComparer<Square> Members
        public int Compare(Square x, Square y)
        {
            if (x.Height == y.Height)
                return 0;
            else if (x.Height > y.Height)
                return 1;
            else if (x.Height < y.Height)
                return -1;
            else
                return -1;
        }
        #endregion
    }

        当调用List<Square>.Sort方法对一个Square对象的列表进行排序时,该列表使用Square对象的IComparable<Square>接口来实现排序。当它们被添加到SortedList<K,V>中时,SortedList<K,V>的Add方法使用该接口对上述对象进行排序。

        设计IComparer<T>接口是用于解决在不同的上下文关系(不同的自定义类型)中以不同的标准排序的问题。这些接口也可以使用户对那些没有实现的类排序。如果想按照宽度对Square对象排序,那么要创建一个名叫CompareHeight的新类型,同样也要实现IComparer<Square>接口,如示例3-2所示:

        当该类传入Sort方法的IComparer参数时,用户可指定不同的规则对Square对象排序。完成的比较方法必须是一致的和全序的,所以当比较函数比较两个对象是否相等时,当一个对象不大于或不小于另一个对象时,将返回绝对真和假的结果。

    提示 为了最好的表现效果,保持CompareTo方法的简洁,因为该方法会被Sort方法调用多次。例如,对一个拥有4个对象的数组排序,Compare方法将被调用10次。

        示例3-3的TestSort方法演示了在Square类和CompareHeight类中怎样使用List<Square> 和SortedList<int,Square>实例。

    //示例3-3. TestSort方法
    public static void TestSort()
    {
        List<Square> listOfSquares = new List<Square>(){
                                            new Square(1,3),
                                            new Square(4,3),
                                            new Square(2,1),
                                            new Square(6,1)};
        // Test a List<String>
        Console.WriteLine("List<String>");
        Console.WriteLine("Original list");
        foreach (Square square in listOfSquares)
        {
            Console.WriteLine(square.ToString());
        }
        Console.WriteLine();
        IComparer<Square> heightCompare = new CompareHeight();
        listOfSquares.Sort(heightCompare);
        Console.WriteLine("Sorted list using IComparer<Square>=heightCompare");
        foreach (Square square in listOfSquares)
        {
            Console.WriteLine(square.ToString());
        }
        Console.WriteLine();
        Console.WriteLine("Sorted list using IComparable<Square>");
        listOfSquares.Sort();
        foreach (Square square in listOfSquares)
        {
            Console.WriteLine(square.ToString());
        }
        // Test a SORTEDLIST
        var sortedListOfSquares = new SortedList<int, Square>(){
                                            { 0, new Square(1,3)},
                                            { 2, new Square(3,3)},
                                            { 1, new Square(2,1)},
                                            { 3, new Square(6,1)}};
        Console.WriteLine();
        Console.WriteLine();
        Console.WriteLine("SortedList<Square>");
        foreach (KeyValuePair<int, Square> kvp in sortedListOfSquares)
        {
            Console.WriteLine(kvp.Key + " : " + kvp.Value);
        }
    }
        上述代码的输出结果如下所示:

    List<String>
    Original list
    Height:1 Width:3
    Height:4 Width:3
    Height:2 Width:1
    Height:6 Width:1
    Sorted list using IComparer<Square>=heightCompare
    Height:1 Width:3
    Height:2 Width:1
    Height:4 Width:3
    Height:6 Width:1
    Sorted list using IComparable<Square>
    Height:2 Width:1
    Height:1 Width:3
    Height:6 Width:1
    Height:4 Width:3
    SortedList<Square>
    0 : Height:1 Width:3
    1 : Height:2 Width:1
    2 : Height:3 Width:3
    3 : Height:6 Width:1

    还可参见

        条目3.3;还有MSDN文档中的“IComparable<T>接口”主题。

    版权说明:作者:张颖希PocketZ's Blog
    出处:http://www.cnblogs.com/PocketZ
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    本文翻译内容取自网络,纯粹是练习英文水平,如有雷同,纯属意外!有不妥之处,欢迎拍砖!

  • 相关阅读:
    Java
    Linux
    Linux
    Linux
    Java
    Ansible
    Ansible
    Java
    ACM&OI 基础数论算法专题
    题解 P4781 【【模板】拉格朗日插值】
  • 原文地址:https://www.cnblogs.com/PocketZ/p/Making_a_Type_Sortable.html
Copyright © 2020-2023  润新知