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

C#之旅(一):泛型和IComparable、IComparer

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

最近在学习C#的一些基础知识,希望以笔记的形式记录下自己在学习当中的所得并与大家分享自己的学习心得,由于还是个初学者还请多多给点意见,大家共同交流共同进步。我也是通过一些比较好的博客边看边学,这里推荐下自我感觉不错的几篇文章,

看后觉对的让我们这些初学者有所得。

 

先从泛型说起   

 

泛型,从大专时候老师就常常说它的重要性,它的地位是如何的高,但没用过即使再好的东西也是无法体会的,唯有一试,方知其厉害。首先学习一门东西,起码要知道它有什么好处,有什么作用,有哪些用武之地,这样才值得我们花大把的时间在它上面。MSDN给出的答案是:“提高的代码可重用性和类型安全性”。

排序是我们编程中会经常碰到的一个问题,排序所使用的算法也有很多,比如冒泡排序,快速排序等等排序算法。比如我现在使用冒泡排序来实现一个很简单的排序功能,对一个int类型的数组进行一个简单的排序

 

 1 public static void BubbleSort(int[] array)
 2 
 3         {
 4 
 5             int length = array.Length;
 6 
 7             int temp;
 8 
 9  
10 
11             for (int i = 0; i < length; i++)
12 
13             {
14 
15                 for (int j = 0; j < length - i - 1; j++)
16 
17                 {
18 
19                     if (array[j] > array[j + 1])
20 
21                     {
22 
23                         temp = array[j];
24 
25                         array[j] = array[j + 1];
26 
27                         array[j + 1= temp;
28 
29                     }
30 
31                 }
32 
33             }
34 
35         }

 

在main函数里调用

 

 1 static void Main(string[] args)
 2         {
 3              int[] array = { 5,4,3,2,1};
 4              Console.WriteLine("排序前:");
 5              for (int i = 0; i < array.Length; i++)
 6              {
 7                  Console.Write("\t"+array[i]);
 8              }
 9              BubbleSort(array);
10              Console.WriteLine("\n\r排序后:");
11              for (int i = 0; i < array.Length; i++)
12              {
13                  Console.Write("\t" + array[i]);
14           }
15 }

 

运行结果:

排序前:

        5       4       3       2       1

排序后:

        1       2       3       4       5

很好的完成了任务,排序功能实现了,现在又碰到这么种情况不单单要对int类型数组排序,还要对double类型的数组排序,很简单只要将上面的代码Copy一份,在做稍微的改变就好:

 

 1 public static void BubbleSort(double[] array)
 2         {
 3             int length = array.Length;
 4             double temp;
 5 
 6             for (int i = 0; i < length; i++)
 7             {
 8                 for (int j = 0; j < length - i - 1; j++)
 9                 {
10                     if (array[j] > array[j + 1])
11                     {
12                         temp = array[j];
13                         array[j] = array[j + 1];
14                         array[j + 1= temp;
15                     }
16                 }
17             }
18         }

 

调用:

 

 1 double[] array = { 5.1,4.1,3.1,2.1,1.1};
 2 
 3             Console.WriteLine("排序前:");
 4 
 5             for (int i = 0; i < array.Length; i++)
 6 
 7             {
 8 
 9                 Console.Write("\t"+array[i]);
10 
11             }
12 
13             BubbleSort(array);
14 
15             Console.WriteLine("\n\r排序后:");
16 
17             for (int i = 0; i < array.Length; i++)
18 
19             {
20 
21                 Console.Write("\t" + array[i]);
22 
23             }

 

输出结果:

排序前:

        5.1     4.1     3.1     2.1     1.1

排序后:

        1.1     2.1     3.1     4.1     5.1

任务完成了,但隐隐感觉这种实现有点问题,感觉不是很完美。现在以这种Copy的方式来达到代码重用显然不是我们想要的。我忽然想到OOD原则的DIP(Dependence Inversion Principle)依赖倒置原则:具体细节应该依赖抽象,抽象不应该依赖具体细节,要依赖于抽象,不依赖于具体。冒泡排序是否就是一个抽象呢,而具体对哪种类型进行排序这里的类型是否就是具体呢!我们现在就是违背了这条原则才会导致路越走越窄。

时代造英雄,这时候泛型也就应运而生。它很好的解决了代码的复用性,将具体类型从排序算法中抽离出来,实现它们二者之间的解耦。

我很快就写出了如下代码:

 

 1 public static void BubbleSort<T>(T[] array) 
 2         {
 3             int length = array.Length;
 4             T temp;
 5 
 6             for (int i = 0; i < length; i++)
 7             {
 8                 for (int j = 0; j < length - i - 1; j++)
 9                 {
10                     if (array[j]> array[j + 1])
11                     {
12                         temp = array[j];
13                         array[j] = array[j + 1];
14                         array[j + 1= temp;
15                     }
16                 }
17             }
18         }

 

这时方法体的声明有点变化,它将类型也当成参数(会发现这里将类型参数取名为T,这不是必须的,可以取任意名称,只是大家习惯使用T来命名),这样就不会依赖具体的某种类型了,按理来说任何类型的排序都适用了,不管以后在碰到其它类型的排序如byte,都可以很好的解决。调用的形式也变成了BubbleSort<int>(array)这种形式,通过方法名后面尖括号还传递具体的某种类型。但还有一个问题会发现就是上面的泛型版的代码根本就连编译都不能通过,问题就出在

 

   if (array[j]> array[j + 1])

 

对T类型进行比较操作是不允许的,因为T是未知的一种类型,T有可能实现了比较运算符也有可能没有。

 

 再说IComparable

 

这个时候就要轮到我们的另外两大主角出场了,首先是IComparable,它的声明如下:

 

1 public interface IComparable
2 
3   { 
4 
5       int CompareTo(Object obj)
6 
7   }

 

MSDN上的解释:定义通用的比较方法,由值类型或类实现以创建类型特定的比较方法。

 

也就是说我们的值类型实现了这个借口,而intdouble这些基本的数据类型属于值类型,那它们就应该实现了这个接口,我们可以看下它们的声明:

 

1 public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>
2 
3 public struct Double : IComparable, IFormattable, IConvertible, IComparable<double>, IEquatable<double>

 

 

重新改写下我们的泛型版的实现:

 

 1 public static void BubbleSort<T>(T[] array) where T : IComparable
 2 
 3         {
 4 
 5             int length = array.Length;
 6 
 7             T temp;
 8 
 9  
10 
11             for (int i = 0; i < length; i++)
12 
13             {
14 
15                 for (int j = 0; j < length - i - 1; j++)
16 
17                 {
18 
19                     if (array[j].CompareTo(array[j + 1]) == 1)
20 
21                     {
22 
23                         temp = array[j];
24 
25                         array[j] = array[j + 1];
26 
27                         array[j + 1= temp;
28 
29                     }
30 
31                 }
32 
33             }
34 
35         }

 

   只要给它加where约束是它必须继承IComrapable接口,在比较时只要调用CompareTo()方法,这时同样还是T类型,也就是一个未知类型,但我们前面已经添加了一个约束必须实现CompareTo()方法,所以这里它可以调用CompareTo()方法进行比较。

   int类型的就这样调用

 

BubbleSort<int>(array);

 

double类型的就这样调用

 

BubbleSort<double>(array);

 

   这样就很好的解决了代码复用,不同的类型复用相同的排序算法,这是我们想要的。而且该算法还可以用于我们自定义的类型,比如我有一个Person类声明如下:

 

 1 public class Person : IComparable
 2     {
 3         public string name;
 4         public int age;
 5         public Person(string name, int age)
 6         {
 7             this.name = name;
 8             this.age = age;
 9         }
10         public int CompareTo(object obj)
11         {
12             Person other = (Person)obj;
13             return this.age.CompareTo(other.age);
14         }
15 }

 

Person它实现了IComparable接口,并在CompareTo方法中返回年龄比较的结果。这样就可以对Person对象实现按年龄来进行排序。

比如我实例化一些对象

 

1 Person[] personArray = { new Person("朱    "25),
2 
3                          new Person("吴朝剑"21),
4 
5                          new Person("叶华斌"23),
6 
7                          new Person("王昌文",22)};

 

   对这些对象进行排序:

 

BubbleSort<Person>(personArray);

 

输出结果:


鲜花

握手

雷人

路过

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

请发表评论

全部评论

专题导读
上一篇:
C语言之基本算法11—牛顿迭代法求平方根发布时间:2022-07-13
下一篇:
C#---可空值类型发布时间: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