• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

编写高质量代码改善C#程序的157个建议——建议10:创建对象时需要考虑是否实现比较器 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

建议10: 创建对象时需要考虑是否实现比较器

有对象的地方就会存在比较,在.NET的世界中也一样。举个最简单的例子,在UI中,有一个10个人的Salary列表。根据排序的需要,列表要支持针对基本工资来罗列Salary。这个时候,接口IComparable就会起作用,代码如下所示:

    class Salary : IComparable  
    {  
        public string Name { get; set; }  
        public int BaseSalary { get; set; }  
        public int Bonus { get; set; }  
     
        #region IComparable 成员  
     
        public int CompareTo(object obj)  
        {  
            Salary staff = obj as Salary;  
            if (BaseSalary > staff.BaseSalary)  
            {  
                return 1;  
            }  
            else if (BaseSalary == staff.BaseSalary)  
            {  
                return 0;  
            }  
            else  
            {  
                return -1;  
            }  
            //return BaseSalary.CompareTo(staff.BaseSalary);  
        }  
     
        #endregion  
    } 

 

注意 上面代码中CompareTo方法有一条注释的代码,其实本方法完全可以使用该注释代码代替,因为利用了整型的默认比较方法。此处未使用本注释代码,是为了更好地说明比较器的工作原理。

实现了接口IComparable后,我们就可以根据BaseSalary对Salary进行排序了,代码如下所示:

    ArrayList companySalary = new ArrayList();  
    companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000 });  
    companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000 });  
    companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000 });  
    companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4000 });  
    companySalary.Sort();  
    foreach (Salary item in companySalary)  
    {  
        Console.WriteLine(item.Name + "\t BaseSalary: " + item.BaseSalary.ToString());  
    } 

 

上面代码的输出如下:

    Jeffry   BaseSalary: 1000  
    Rose     BaseSalary: 2000  
    Mike     BaseSalary: 3000  
    Steve    BaseSalary: 4000 

 

现在,问题来了:如果不想以基本工资BaseSalary进行排序,而是以奖金Bonus进行排序,该如何处理呢?这个时候,接口IComparer的作用就体现出来了,可以使用IComparer来实现一个自定义的比较器。如下所示:

    class BonusComparer : IComparer  
    {  
        #region IComparer 成员  
     
        public int Compare(object x, object y)  
        {  
            Salary s1 = x as Salary;  
            Salary s2 = y as Salary;  
            return s1.Bonus.CompareTo(s2.Bonus);  
        }  
     
        #endregion  
    } 

 

我们在排序的时候为Sort方法提供此比较器,代码如下所示:

    ArrayList companySalary = new ArrayList();  
    companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 });  
    companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 4000 });  
    companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 6000 });  
    companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4000, Bonus = 3000 });  
    companySalary.Sort(new BonusComparer());    //提供一个非默认的比较器  
    foreach (Salary item in companySalary)  
    {  
        Console.WriteLine(string.Format("Name:{0} \tBaseSalary:{1} \tBonus:{2}",  
            item.Name, item.BaseSalary, item.Bonus));  
    } 

 

输出结果如下:

    Name:Mike       BaseSalary:3000         Bonus:1000  
    Name:Steve      BaseSalary:4000         Bonus:3000  
    Name:Rose       BaseSalary:2000         Bonus:4000  
    Name:Jeffry     BaseSalary:1000         Bonus:6000 

 

如果我们稍有经验,就会发现上面的代码使用了一个已经不建议使用的集合类ArrayList(当泛型出来后,就建议尽量不使用所有非泛型集合类)。至于原因,从上面的代码中我们也可以看出端倪。 注意查看代码中的Compare函数,如:

    public int Compare(object x, object y)  
    {  
        Salary s1 = x as Salary;  
        Salary s2 = y as Salary;  
        return s1.Bonus.CompareTo(s2.Bonus);  
    } 

 

我们发现这个函数进行了转型,这是会影响性能的。如果集合中有成千上万个复杂的实体对象,在排序的时候所耗费掉的性能就是可观的;而泛型的出现,可以避免运行时转型。 因此,以上代码中的ArrayList,应该换成List,对应地,我们就该实现IComparable和IComparer。最终的代码应该像下面这样:

     
    class Salary : IComparable<Salary> 
    {  
        public string Name { get; set; }  
        public int BaseSalary { get; set; }  
        public int Bonus { get; set; }  
     
        #region IComparable<Salary> 成员  
     
        public int CompareTo(Salary other)  
        {  
            return BaseSalary.CompareTo(other.BaseSalary);  
        }  
     
        #endregion  
    }  
     
    class BonusComparer : IComparer<Salary> 
    {  
        #region IComparer<Salary> 成员  
     
        public int Compare(Salary x, Salary y)  
        {  
            return x.Bonus.CompareTo(y.Bonus);  
        }  
     
         #endregion  
    }

    static void Main(string[] args)  
    {  
        List<Salary> companySalary = new List<Salary>()  
            {  
                new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 },  
                new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 4000 },  
                new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 6000 },  
                new Salary() { Name = "Steve", BaseSalary = 4000, Bonus = 3000 }  
            };  
        companySalary.Sort(new BonusComparer());    //提供一个非默认的比较器  
        foreach (Salary item in companySalary)  
        {  
            Console.WriteLine(string.Format("Name:{0} \tBaseSalary:{1} \tBonus:{2}",  
                item.Name, item.BaseSalary, item.Bonus));  
        }  
    }  

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#中HttpWebRequest的用法详解发布时间:2022-07-13
下一篇:
C#Decimal四舍五入到指定小数位数发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap