当前位置:嗨网首页>书籍在线阅读

20-泛型约束

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

16.5.2 泛型约束

上述例子中,如果保持原冒泡算法中的“if (array[j] < array[j - 1])”语句不变,或去掉“where T : IComparable”代码部分,程序将出现编译错误。这主要是因为泛型T是后来绑定的,因此在编译时编译器无法得知T的实例是采用什么样的标准来进行大小比较的。对于上例中的简单数据类型比较,我们只需给参数类型T添加“where T : IComparable”类型约束,但如何用泛型方法实现对复杂数据类型的比较呢?下面我们举例说明。

假如有一个自定义的类Book,它包含两个私有字段_id和_title,两个外部属性ID和Title,以及两个构造函数,代码如下。

01  public class Book        
02  {        
03           private int _id;              //表示ID的字段
04           private String _title;        //表示书名的字段
05           public Book() { }             //无参数构造函数
06           public Book(int id,string title) {
07                  this._id=id;
08                  this._title=title;     //有参数构造函数
09          }
10          public int ID {
11                  get{return _id;}
12                  set{_id=value;}
13          }        //表示ID的属性
14          public string  Title{         //表示书名的属性
15                  get{return _ title;}
16                  set{_ title=value;}
17          }
18  }

现在创建一个Book型的数组,然后用SortHelper类中的泛型方法对其进行排序。

01  public class Test        
02  {        
03           static void Main()  {        
04           Book[] bookArray=new Book[2];        
05           Book book1=new Book(1,"guowenhui,");        
06           Book book2=new Book(2,"ongyaguang,");
07           bookArray[0]=book1;
08           bookArray[1]=book2;        //有参数构造函数
09           SortHelper<Book>  sort=new SortHelper<Book>();
10           Sort.BubbleSort(bookArray);
11           foreach (Book b in bookArray) {
12                  Console.WriteLine(“Id:{0}”, b.ID);
13                  Console.WriteLine(“Title:{0}\n”, b.Title);        //表示客户ID的属性
14           }
15          }
16  }

上面的代码将不能通过编译,这是因为我们现在要比较的是复杂类型对象Book,book1和book2到底谁大,这涉及一个判断依据的问题。如何来实现这种复杂类型对象的比较呢?答案是让需要进行比较的对象类实现IComparable接口。也就是说,只有实现了IComparable接口的类型才能作为类型参数被传入,即我们需要对传入参数的类型进行一些约束,这就是我们要讲的泛型约束。

接下来我们就让Book类来实现IComparable接口,即在类的内部定义一个比较的标准,我们这里采用的标准是比较ID,Book类中变化的代码如下。

01  public class Book: IComparable        
02  {
03           public int CompareTo(object obj)  //实现接口
04           {
05                  Book book2=(Book)obj;
06                  return this.ID.CompareTo(book2.ID);
07          }
08   ……        //其他代码不变
09  }

再次运行测试代码,将正确输出书本ID的比较结果。

C#泛型要求对“所有泛型类型或泛型方法的类型参数”的任何假定,都要基于“显式的约束”,以维护C#所要求的类型安全。“显式约束”由where子句表达,可以指定“基类约束”、“接口约束”、“构造器约束”、“值类型/引用类型约束”四种约束(在本例中我们实现的是接口约束)。“显式约束”并非必需,如果没有指定“显式约束”,范型类型参数将只能访问System.Object类型中的公有方法。