用脑图忆泛型

用泛型已经有一段时间了,回过头来看时,发现之前用的太简单了,现在回过头了深入学习下。主要再学习参数的约束

什么是泛型泛型 (2) (2)

    泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型及其方法的参数类型出现。泛型方法可以将其类型参数用作其返回值的类型或者其某个形参的类型。

优点

使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。

类型参数的约束

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的 

使用约束的原因

如果要检查泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。这种保证是通过对泛型类定义应用一个或多个约束获得的。例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型的方法。约束是使用上下文关键字 where 应用的

约束说明

  • T:结构
  • 类型参数必须是值类型。
  • T:类
  • 类型参数必须是引用类型,包括任何类、接口、委托或数组类型。
  • T:new()
  • 类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。
  • T:<基类名>
  • 类型参数必须是指定的基类或派生自指定的基类。
  • T:<接口名称>
  • 类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
  • T:U
  • 为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。
   1: public class Employee
   2: {
   3:     private string name;
   4:     private int id;
   5:  
   6:     public Employee(string s, int i)
   7:     {
   8:         name = s;
   9:         id = i;
  10:     }
  11:  
  12:     public string Name
  13:     {
  14:         get { return name; }
  15:         set { name = value; }
  16:     }
  17:  
  18:     public int ID
  19:     {
  20:         get { return id; }
  21:         set { id = value; }
  22:     }
  23: }
  24:  
  25: public class GenericList<T> where T : Employee
  26: {
  27:     private class Node
  28:     {
  29:         private Node next;
  30:         private T data;
  31:  
  32:         public Node(T t)
  33:         {
  34:             next = null;
  35:             data = t;
  36:         }
  37:  
  38:         public Node Next
  39:         {
  40:             get { return next; }
  41:             set { next = value; }
  42:         }
  43:  
  44:         public T Data
  45:         {
  46:             get { return data; }
  47:             set { data = value; }
  48:         }
  49:     }
  50:  
  51:     private Node head;
  52:  
  53:     public GenericList() //constructor
  54:     {
  55:         head = null;
  56:     }
  57:  
  58:     public void AddHead(T t)
  59:     {
  60:         Node n = new Node(t);
  61:         n.Next = head;
  62:         head = n;
  63:     }
  64:  
  65:     public IEnumerator<T> GetEnumerator()
  66:     {
  67:         Node current = head;
  68:  
  69:         while (current != null)
  70:         {
  71:             yield return current.Data;
  72:             current = current.Next;
  73:         }
  74:     }
  75:  
  76:     public T FindFirstOccurrence(string s)
  77:     {
  78:         Node current = head;
  79:         T t = null;
  80:  
  81:         while (current != null)
  82:         {
  83:             //The constraint enables access to the Name property.
  84:             if (current.Data.Name == s)
  85:             {
  86:                 t = current.Data;
  87:                 break;
  88:             }
  89:             else
  90:             {
  91:                 current = current.Next;
  92:             }
  93:         }
  94:         return t;
  95:     }
  96: }

约束使得泛型类能够使用 Employee.Name 属性,因为类型为 T 的所有项都保证是 Employee 对象或从 Employee 继承的对象。

可以对同一类型参数应用多个约束,并且约束自身可以是泛型类型,当与其他约束一起使用时,new() 约束必须最后指定

 

泛型代码中的默认关键字

在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T:

  • T 是引用类型还是值类型。

  • 如果 T 为值类型,则它是数值还是结构。

给定参数化类型 T 的一个变量 t,只有当 T 为引用类型时,语句 t = null 才有效;只有当 T 为数值类型而不是结构时,语句 t = 0 才能正常使用。解决方案是使用 default 关键字,此关键字对于引用类型会返回空,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或空的每个结构成员,具体取决于这些结构是值类型还是引用类型。以下来自GenericList<T> 类的示例显示了如何使用 default 关键字

   1: public class GenericList<T>
   2: {
   3:     private class Node
   4:     {
   5:         //...
   6:  
   7:         public Node Next;
   8:         public T Data;
   9:     }
  10:  
  11:     private Node head;
  12:  
  13:     //...
  14:  
  15:     public T GetNext()
  16:     {
  17:         T temp = default(T);
  18:  
  19:         Node current = head;
  20:         if (current != null)
  21:         {
  22:             temp = current.Data;
  23:             current = current.Next;
  24:         }
  25:         return temp;
  26:     }
  27: }

以上是以前不熟悉的东西,作一下记录。脑图下载:https://files.cnblogs.com/tianyaxiang/%E6%B3%9B%E5%9E%8B.rar

posted on 2011-07-14 18:09  tianyaxiang  阅读(1745)  评论(1编辑  收藏  举报

导航