C#比较类/接口、Dictionary 排序

首先看下List.Sort()方法:

public void Sort(int index, int count, IComparer<T> comparer);  //指定范围排序
public void Sort(Comparison<T> comparison);
public void Sort();
public void Sort(IComparer<T> comparer);

一.Comparison<T>

public delegate int Comparison<in T>(T x, T y);

概念:表示用于比较相同类型的两个对象的方法。

  1. 解释:使用delegate,是为了将方法视为变量并可作为参数传递的实体。
  2. 对Dictionary 排序:
Dictionary<string, int> dic = new Dictionary<string, int>();
dic.Add("index.html", 50);
dic.Add("product.html", 13);
dic.Add("aboutus.html", 4);
dic.Add("online.aspx", 22);
dic.Add("news.aspx", 18);

//第一种
List<KeyValuePair<string, int>> list1 = new List<KeyValuePair<string, int>>(dic);
list1.Sort(h1);

//第二种
List<KeyValuePair<string, int>> list2 = new List<KeyValuePair<string, int>>(dic);
list1.Sort(delegate (KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
{
    return s2.Value.CompareTo(s1.Value);
});

//第三种
List<KeyValuePair<string, int>> list3 = new List<KeyValuePair<string, int>>(dic);
list2.Sort((s1, s2) => { return s1.Value.CompareTo(s2.Value); });

public static int h1(KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
{
    return s2.Value.CompareTo(s1.Value);
}        

二. Comparer<T> ClassIComparer<T>

  1. 概念:为 IComparer<T> 泛型接口实现提供的基类。
public abstract class Comparer<T> : IComparer, IComparer<T>
{
    protected Comparer();
    public static Comparer<T> Default { get; }
    public static Comparer<T> Create(Comparison<T> comparison);
    public abstract int Compare(T x, T y);
}
  1. Comparer<T>和 IComparer<T>的区别:
  • Comparer<T>是类,并提供了默认比较器,也就是说,如果需要自定义默认比较器,需要自行实现IComparer<T>接口
  • 使用Comparer<T>.Default来获取默认比较器

三. IComparable<T>

与此实例比较的对象
IComparable<T>,实现接口:IComparer<T> IComparer

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

四.Comparer<T> Class、IComparer<T>、IComparable<T>官方案例

class Test
{
    static void Main(string[] args)
    {
        List<Box> Boxes = new List<Box>();
        Boxes.Add(new Box(4, 20, 14));
        Boxes.Add(new Box(12, 12, 12));
        Boxes.Add(new Box(8, 20, 10));
        Boxes.Add(new Box(6, 10, 2));
        Boxes.Add(new Box(2, 8, 4));
        Boxes.Add(new Box(2, 6, 8));
        Boxes.Add(new Box(4, 12, 20));
        Boxes.Add(new Box(18, 10, 4));
        Boxes.Add(new Box(24, 4, 18));
        Boxes.Add(new Box(10, 4, 16));
        Boxes.Add(new Box(10, 2, 10));
        Boxes.Add(new Box(6, 18, 2));
        Boxes.Add(new Box(8, 12, 4));
        Boxes.Add(new Box(12, 10, 8));
        Boxes.Add(new Box(14, 6, 6));
        Boxes.Add(new Box(16, 6, 16));
        Boxes.Add(new Box(2, 8, 12));
        Boxes.Add(new Box(4, 24, 8));
        Boxes.Add(new Box(8, 6, 20));
        Boxes.Add(new Box(18, 18, 12));

        //使用继承了Comparer<T>的比较器,进行排序。里面覆写了Compare(T a,T b)方法
        Boxes.Sort(new BoxLengthFirst());  

        foreach (Box bx in Boxes)
        {
            Console.WriteLine("{0}\t{1}\t{2}",
                bx.Height.ToString(), bx.Length.ToString(),
                bx.Width.ToString());
        }

        Console.WriteLine("===============");

        //获取默认比较器
        Comparer<Box> defComp = Comparer<Box>.Default;  

        // Calling Boxes.Sort() with no parameter
        // is the same as calling Boxs.Sort(defComp)
        // because they are both using the default comparer.
        // 等于调用Boxs.Sort(defComp);
        Boxes.Sort();

        foreach (Box bx in Boxes)
        {
            //输出高、长、宽
            Console.WriteLine("{0}\t{1}\t{2}",
                bx.Height.ToString(), bx.Length.ToString(),
                bx.Width.ToString());
        }

        // This explicit interface implementation
        // compares first by the length.
        // Returns -1 because the length of BoxA
        // is less than the length of BoxB.
        BoxLengthFirst LengthFirst = new BoxLengthFirst();

        Comparer<Box> bc = (Comparer<Box>)LengthFirst;

        Box BoxA = new Box(2, 6, 8);
        Box BoxB = new Box(10, 12, 14);
        int x = LengthFirst.Compare(BoxA, BoxB);
        Console.WriteLine();
        Console.WriteLine(x.ToString());
 
        Console.ReadLine();
    }
}
public class BoxLengthFirst : Comparer<Box>
{
    //父类抽象方法 Compare
    // Compares by Length, Height, and Width.
    public override int Compare(Box x, Box y)
    {
        if (x.Length.CompareTo(y.Length) != 0)
        {
            return x.Length.CompareTo(y.Length);
        }
        else if (x.Height.CompareTo(y.Height) != 0)
        {
            return x.Height.CompareTo(y.Height);
        }
        else if (x.Width.CompareTo(y.Width) != 0)
        {
            return x.Width.CompareTo(y.Width);
        }
        else
        {
            return 0;
        }
    }

}


// This class is not demonstrated in the Main method
// and is provided only to show how to implement
// the interface. It is recommended to derive
// from Comparer<T> instead of implementing IComparer<T>.

//没有在Main方法里演示,推荐使用继承Comparer<T>的方法。
public class BoxComp : IComparer<Box>
{
    // Compares by Height, Length, and Width.
    public int Compare(Box x, Box y)
    {
        if (x.Height.CompareTo(y.Height) != 0)
        {
            return x.Height.CompareTo(y.Height);
        }
        else if (x.Length.CompareTo(y.Length) != 0)
        {
            return x.Length.CompareTo(y.Length);
        }
        else if (x.Width.CompareTo(y.Width) != 0)
        {
            return x.Width.CompareTo(y.Width);
        }
        else
        {
            return 0;
        }
    }
}

public class Box : IComparable<Box>
{
    public Box(int h, int l, int w)
    {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }
    public int Height { get; private set; }
    public int Length { get; private set; }
    public int Width { get; private set; }

    public int CompareTo(Box other)
    {
        // Compares Height, Length, and Width.
        if (this.Height.CompareTo(other.Height) != 0)
        {
            return this.Height.CompareTo(other.Height);
        }
        else if (this.Length.CompareTo(other.Length) != 0)
        {
            return this.Length.CompareTo(other.Length);
        }
        else if (this.Width.CompareTo(other.Width) != 0)
        {
            return this.Width.CompareTo(other.Width);
        }
        else
        {
            return 0;
        }
    }
}

五. Comparison<T>、 Comparer<T>、 System.IComparable、IComparable<T>的区别

  1. Comparison<T>,继承委托。开发人员可以在外部写个用于比较大小的函数,然后作为 Comparison<T>类型的参数传入,进行比较,非常方便。

  2. 派生自 Comparer<T> 类和实现 System.IComparable 接口之间的差异如下:

  • 若要指定默认情况下(Default获取)应如何比较两个对象,请在类中实现 System.IComparable 接口。 这可确保排序操作将使用您提供的默认比较代码。

  • 若要定义要使用的比较器而不是默认比较器,请从 Comparer<T> 类派生。 然后,您可以在采用比较器作为参数的排序操作中使用此比较器。

  1. Default 属性返回的对象使用 System.IComparable<T> 泛型接口来比较两个对象。 如果类型 T 未实现 System.IComparable<T> 泛型接口,Default 属性返回使用 System.IComparable 接口的 Comparer<T>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352