C# IComparable

时间:2020-05-02 11:56:31   收藏:0   阅读:99

IComparable是C#和.NET中确认对象之间相对顺序的标准协议之一。

准确的来说IComparable包括IComparable和IComparable<T>两个接口。

而另外一种则是我们运用的非常之多的“<”和“>”运算符。

IComparablede的定义方式如下:

 public interface IComparable
    {
        int CompareTo(object othor);
    }
    public interface IComparable<in T>
    {
        int CompareTo(T othor);
    }

这两个接口实现了相同的功能。对于值类型,泛型安全的接口执行速度比非泛型要快。

它们的CompareTo方法按照如下的方式执行。

                Console.WriteLine("A".CompareTo("B"));//-1
                Console.WriteLine("B".CompareTo("B"));//0
                Console.WriteLine("B".CompareTo("A"));//1

上面这个例子可以看出来String类型是有实现IComparable接口的,那不然怎么能使用这个方法。

那当我们自己在创建一个结构体想要提升它的比较效率的时候,我们自己也能通过IComparable来实现。

上代码

  public struct Note : IComparable<Note>, IEquatable<Note>, IComparable
    {
        int _semitonesFromA;
        public int SemitonesFromA { get => _semitonesFromA; }

        public Note(int semitonesFromA)
        {
            _semitonesFromA = semitonesFromA;
        }
        /// <summary>
        /// 实现泛型接口
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(Note other)
        {
            if (Equals(other)) return 0;
            return _semitonesFromA.CompareTo(other._semitonesFromA);
        }
        /// <summary>
        /// 实现非泛型接口
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        int IComparable.CompareTo(object obj)
        {
            if (!(obj is Note))
                throw new InvalidOperationException("不是Note");
            return CompareTo((Note)obj);
        }
        /*重载“<”和“>”运算符*/
        public static bool operator >(Note n1, Note n2) => n1.CompareTo(n2) > 0;
        public static bool operator <(Note n1, Note n2) => n1.CompareTo(n2) < 0;
        /// <summary>
        /// 实现IEquatable
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool Equals(Note other) => other._semitonesFromA == this._semitonesFromA;
        /// <summary>
        /// 重写Equals
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (!(obj is Note)) return false;
            return Equals((Note)obj);
        }
        /// <summary>
        /// 重写GetHashCode
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this._semitonesFromA.GetHashCode();
        }
        /*重载==和!=运算符*/
        public static bool operator ==(Note n1, Note n2) => n1.Equals(n1);
        public static bool operator !=(Note n1, Note n2) => !n1.Equals(n1);
    }

测试

                var note = new Note(9);
                var note2 = new Note(10);
                var note3 = new Note(11);
                Console.WriteLine(note2.CompareTo(note3));//-1
                Console.WriteLine(note2.CompareTo(note2));//0
                Console.WriteLine(note3.CompareTo(note));//1
                Console.WriteLine(note3 > note2);//true
                Console.WriteLine(note2 < note);//false

上面这个例子重载了IComparable接口并且重载了运算符“<”和“>”。同时还实现了IEquatable接口,详情见我博客相等比较

这里就说说为啥要重载运算符“<”和“>”。

运算符“<”和“>”的是实现在功能上和IComparable接口时一致的。当然这是整个.NET Framework的标准做法。

我们的例子重载了运算符“<”和“>”,但实际情况下实现IComparable并不一定需要实现运算符“<”和“>”,但是如果重载运算符“<”和“>”那么就必须要实现IComparable。

对于这个必须,我的理解是运算符“<”和“>”的实现是必须要基于IComparable的。

那实现IComparable时,我们什么样的情况下,需要实现运算符“<”和“>”呢。

所有的数值类型基本都实现了运算符“<”和“>”,因为数值类型都符合这三个条件。

System.String就不满足最后一点bool ok="Back">"Anne"这句代码就会报错。

 

原文:https://www.cnblogs.com/aqgy12138/p/12816907.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!